📌  相关文章
📜  对和的和与给定数组的按位与的按位与之和

📅  最后修改于: 2021-05-25 01:37:52             🧑  作者: Mango

给定的阵列ARR []N个整数的,任务是找到按位AND(ARR [I] + ARR [j]的)和按位与ARR [I]之和的常用3 [j]的每个对给定数组中的元素(arr [i],arr [j])。由于总和可能非常大,请以模(10 9 + 7)进行打印。

例子:

天真的方法:最简单的方法是从给定的数组生成所有可能的对,并检查是否存在满足给定条件的对。如果发现是真的,则这对。检查所有对之后,打印结果计数
时间复杂度: O(N 2 )
辅助空间: O(1)

高效的方法:可以基于以下观察来优化上述方法:

  • 考虑到一对(X,Y)时,按位与在比特,说b1,那么(X + Y)也必须具有b比特为一组位在作出贡献b比特。
  • 仅考虑这样的对的两个数目中的最后b个比特,可以观察到要满足上述条件,b个比特和第(b + 1)比特,都必须被设置。
  • 因此,从上述步骤可以得出,要满足上述条件,应满足以下条件:
  • 因此,该任务减少了找到每个位位置满足上述条件的对的数目,并针对0≤b <31将结果增加cnt * 2 b的值。

请按照以下步骤解决问题:

  • 初始化一个变量,例如ans ,以存储结果总和。
  • 迭代范围[ 0,30]并执行以下操作:
    • 初始化一个向量V ,该向量存储满足上述条件的对。
    • 遍历给定数组arr []并将值arr [j] –(arr [j] >>(i + 1))*(1 <<(i + 1))以M为模,插入向量V中,如果(( arr [j] >>(i + 1))&1)为真。
    • 将向量V升序排序。
    • 遍历向量V并执行以下操作:
      • 计算值2 (i + 1) + 2 i – V [j]并将其存储在变量Y中
      • 查找V中大于或等于YV中的点数,并将其存储在变量中,例如cnt,cnt = V.size()–(lower_bound(V.begin()+ j + 1,V.end (),Y)– V.begin())。
      • ans更新为ans =(ans + cnt * 2 i )%M
  • 完成上述步骤后,输出ans的值作为结果。

下面是上述方法的实现:

C++14
// C++ program for the above approach
 
#include 
#define M 1000000007
using namespace std;
 
// Function to find the sum of Bitwise AND
// of sum of pairs and their Bitwise AND
// from a given array
void findSum(int A[], int N)
{
    // Stores the total sum
    long long ans = 0;
 
    for (int i = 0; i < 30; i++) {
 
        vector vec;
 
        for (int j = 0; j < N; j++) {
 
            // Check if jth bit is set
            if ((A[j] >> i) & 1) {
 
                // Stores the right shifted
                // element by(i+1)
                long long X = (A[j] >> (i + 1));
 
                // Update the value
                // of X
                X = X * (1 << (i + 1));
                X %= M;
 
                // Push in vector vec
                vec.push_back(A[j] - X);
            }
        }
        // Sort the vector in
        // ascending order
        sort(vec.begin(), vec.end());
 
        // Traverse the vector vec
        for (int j = 0; j < vec.size(); j++) {
 
            // Stores the value
            // 2^(i+1)- 2^(i)- vec[j]
            int Y = (1 << (i + 1))
                    + (1 << i)
                    - vec[j];
 
            // Stores count of numbers
            // whose value > Y
            int idx = lower_bound(
                          vec.begin() + j + 1,
                          vec.end(), Y)
                      - vec.begin();
 
            // Update the ans
            ans += (vec.size() - idx)
                   * 1ll * (1 << i);
 
            ans %= M;
        }
    }
 
    // Return the ans
    cout << ans % M << endl;
}
 
// Driver Code
int main()
{
    int arr[] = { 1, 3, 3 };
    int N = sizeof(arr) / sizeof(arr[0]);
    findSum(arr, N);
 
    return 0;
}


Python3
# Python 3 program for the above approach
M = 1000000007
from bisect import bisect_left
 
# Function to find the sum of Bitwise AND
# of sum of pairs and their Bitwise AND
# from a given array
def findSum(A, N):
   
    # Stores the total sum
    ans = 0
 
    for i in range(30):
        vec = []
 
        for j in range(N):
            # Check if jth bit is set
            if ((A[j] >> i) & 1):
                # Stores the right shifted
                # element by(i+1)
                X = (A[j] >> (i + 1))
 
                # Update the value
                # of X
                X = X * (1 << (i + 1))
                X %= M
 
                # Push in vector vec
                vec.append(A[j] - X)
 
        # Sort the vector in
        # ascending order
        vec.sort(reverse=False)
 
        # Traverse the vector vec
        for j in range(len(vec)):
           
            # Stores the value
            # 2^(i+1)- 2^(i)- vec[j]
            Y = (1 << (i + 1)) + (1 << i) - vec[j]
 
            # Stores count of numbers
            # whose value > Y
            temp = vec[j+1:]
            idx = int(bisect_left(temp,Y))
 
            # Update the ans
            ans += ((len(vec) - idx) * (1 << i))
 
            ans %= M
    ans /= 7
 
    # Return the ans
    print(int(ans % M))
 
# Driver Code
if __name__ == '__main__':
    arr =  [1, 3, 3]
    N = len(arr)
    findSum(arr, N)
 
    # This code is contributed by SURENNDRA_GANGWAR.


输出:
2

时间复杂度: O(N * log N)
辅助空间: O(N)