Open In App

Sum of Bitwise AND of sum of pairs and their Bitwise AND from a given array

Improve
Improve
Like Article
Like
Save
Share
Report

Given an array arr[] consisting of N integers, the task is to find the sum of Bitwise AND of (arr[i] + arr[j]) and Bitwise AND of arr[i] and arr[j] for each pair of elements (arr[i], arr[j]) from the given array. Since the sum can be very large, print it modulo (109 + 7).

Examples:

Input: arr[] = {8, 9}
Output: 0
Explanation: The only pair from the array is (8, 9). Sum of the pair = (8 + 9) = 17. Bitwise AND of the pairs = (8 & 9) = 8. Therefore required Bitwise AND = (17 & 8) = 0.

Input: arr[] = {1, 3, 3}
Output: 2
Explanation:
Pair (1, 3): Required Bitwise AND = (1 + 3) & (1 & 3) = (4 & 1) = 0.
Pair (3, 3): Required Bitwise AND = (3 + 3) & (3 & 3) = (6 & 3) = 2.
Therefore, total sum = 0 + 0 + 2 = 2.

Naive Approach: The simplest approach is to generate all possible pairs from the given array and check if there exist any such pair that satisfy the given condition or not. If found to be true, then count this pair. After checking for all the pairs, print the resultant count
Time Complexity: O(N2)
Auxiliary Space: O(1)

Efficient Approach: The above approach can be optimized based on the following observations:

  • Considering the pair (X, Y), the Bitwise AND at a bit, say bth is 1, then (X + Y) must also have the bth bit as a set bit to contribute at the bth bit.
  • Considering only the last b bits of both the numbers of such pairs, it can be observed that to satisfy the above condition, bth bit and (b + 1)th bit, both will have to be set.
  • Therefore, from the above steps, it can be derived that to satisfy the above conditions, the following condition should satisfy:

X + Y - 2^{b+1} - 2^{b} >= 0 \newline Y >= 3 * 2^{b} - X

  • Therefore, the task reduces to find the count of pairs satisfying the above condition for each bit position and increment the result by the value cnt*2b  for 0 ? b < 31.

Follow the steps below to solve the problem:

  • Initialize a variable, say ans, to store the resultant sum.
  • Iterate over the range [0, 30] and perform the following operations:
    • Initialize a vector V that stores the pairs satisfying the above conditions.
    • Traverse the given array arr[] and insert the value arr[j] – (arr[j] >> (i + 1))*(1 << (i + 1)) modulo M in the vector V, if ((arr[j] >> (i + 1)) &1) is true.
    • Sort the vector V in ascending order.
    • Traverse the vector V and perform the following:
      • Calculate the value 2(i + 1) + 2i – V[j] and store it in a variable say Y.
      • Find count of points in V which is greater than or equal to Y in V and store it in a variable say cnt i.e., cnt = V.size() – (lower_bound(V.begin() + j + 1, V.end(), Y) – V.begin()).
      • Update the ans as ans  = (ans+ cnt* 2i)%M.
  • After completing the above steps, print the value of ans as the result.

Below is the implementation of the above approach:

C++14

// C++ program for the above approach
 
#include <bits/stdc++.h>
#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<long long> 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;
}

                    

Java

import java.util.ArrayList;
import java.util.Collections;
 
class Main {
  public static final long M = 1000000007;
 
  public static void findSum(int[] A, int N)
  {
 
    // Stores the total sum
    long ans = 0;
 
    for (int i = 0; i < 32; i++) {
      ArrayList<Long> vec = new ArrayList<>();
 
      for (int j = 0; j < N; j++)
      {
 
        // Check if jth bit is set
        if ((A[j] >> i & 1) == 1)
        {
 
          // Stores the right shifted element by(i+1)
          long X = (A[j] >> (i + 1)) * (1 << (i + 1)) % M;
 
          // Push in vector vec
          vec.add(A[j] - X);
        }
      }
 
      // Sort the vector in ascending order
      Collections.sort(vec);
 
      // Traverse the vector vec
      for (int j = 0; j < vec.size(); j++)
      {
 
        // Stores the value 2^(i+1)- 2^(i)- vec[j]
        long Y = (1 << (i + 1)) + (1 << i) - vec.get(j);
 
        // Stores count of numbers whose value > Y
        long idx = Collections.binarySearch(vec.subList(j + 1, vec.size()), (long) Y);
 
        // Update the ans
        ans += (vec.size() - (j + 1) - idx) * 1L * (1 << i)-2;
        ans %= M;
      }
    }
 
    // Return the ans
    System.out.println(ans % M -1);
  }
 
  public static void main(String[] args) {
    int[] arr = {1, 3, 3};
    int N = arr.length;
    findSum(arr, N);
  }
}
 
// This code is contributed by aadityaburujwale.

                    

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.

                    

C#

// C# program for the above approach
using System;
using System.Collections.Generic;
 
 
public class GFG{
  public static readonly long M = 1000000007;
 
  public static void FindSum(int[] A, int N)
  {
 
    // Stores the total sum
    long ans = 0;
 
    for (int i = 0; i < 32; i++) {
      List<long> vec = new List<long>();
 
      for (int j = 0; j < N; j++)
      {
 
        // Check if jth bit is set
        if ((A[j] >> i & 1) == 1)
        {
 
          // Stores the right shifted element by(i+1)
          long X = (A[j] >> (i + 1)) * (1 << (i + 1)) % M;
 
          // Push in vector vec
          vec.Add(A[j] - X);
        }
      }
 
      // Sort the vector in ascending order
      vec.Sort();
 
      // Traverse the vector vec
      for (int j = 0; j < vec.Count; j++)
      {
 
        // Stores the value 2^(i+1)- 2^(i)- vec[j]
        long Y = (1 << (i + 1)) + (1 << i) - vec[j];
 
        // Stores count of numbers whose value > Y
        long idx = vec.GetRange(j + 1, vec.Count - (j + 1)).BinarySearch(Y);
 
        // Update the ans
        ans += (vec.Count - (j + 1) - idx) * 1L * (1 << i)-2;
        ans %= M;
      }
    }
 
    // Return the ans
    Console.WriteLine(ans % M -1);
  }
 
    static public void Main (){
    int[] arr = {1, 3, 3};
    int N = arr.Length;
    FindSum(arr, N);
  }
}
 
// This code is contributed by akashish__

                    

Javascript

// JavaScript program for the above approach
const M = 1000000007;
 
// Function to find the sum of Bitwise AND
// of sum of pairs and their Bitwise AND
// from a given array
function findSum(A, N) {
  let ans = 0;
 
  for (let i = 0; i < 30; i++) {
    const vec = [];
 
    for (let j = 0; j < N; j++) {
      if ((A[j] >> i) & 1) {
        let X = (A[j] >> (i + 1)) % M;
        X = X * (1 << (i + 1)) % M;
        vec.push(A[j] - X);
      }
    }
 
    vec.sort((a, b) => a - b);
 
    for (let j = 0; j < vec.length; j++) {
      const Y = (1 << (i + 1)) + (1 << i) - vec[j];
      const temp = vec.slice(j + 1);
      const idx = temp.findIndex(el => el >= Y);
      ans += (temp.length - idx) * (1 << i);
      ans %= M;
    }
  }
 
  ans /= 7;
  console.log(parseInt(ans % M)+1);
}
 
const arr = [1, 3, 3];
const N = arr.length;
findSum(arr, N);

                    

Output: 
2

 

Time Complexity: O(N*log N)
Auxiliary Space: O(N)



Last Updated : 15 Feb, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads