📌  相关文章
📜  来自给定数组的对和它们的按位 AND 的按位 AND 的总和

📅  最后修改于: 2021-09-06 06:07:37             🧑  作者: Mango

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

例子:

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

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

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

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

  • 初始化一个变量,比如ans ,以存储结果总和。
  • 迭代范围[0, 30]并执行以下操作:
    • 初始化一个向量V来存储满足上述条件的对。
    • 遍历给定数组arr[]并在向量V 中插入值arr[j] – (arr[j] >> (i + 1))*(1 << (i + 1)) modulo M ,如果(( arr[j] >> (i + 1)) &1)为真。
    • 按升序对向量 V 进行排序。
    • 遍历向量V并执行以下操作:
      • 计算值2 (i + 1) + 2 i – V[j]并将其存储在变量Y 中
      • 查找 V中大于或等于V 中Y的点数并将其存储在变量中,例如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)

如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live