📜  所有子数组的按位与之和

📅  最后修改于: 2021-05-05 02:22:51             🧑  作者: Mango

给定一个由N个正整数组成的数组,请找到按位与该数组所有可能的子数组的总和。

例子:

Input : arr[] = {1, 5, 8}
Output : 15
Bit-wise AND of {1} = 1
Bit-wise AND of {1, 5} = 1
Bit-wise AND of {1, 5, 8} = 0 
Bit-wise AND of {5} = 5
Bit-wise AND of {5, 8} = 0
Bit-wise AND of {8} = 8

Sum = 1 + 1 + 0 + 5 + 0 + 8 =  15

Input : arr[] =  {7, 1, 1, 5}
Output : 20

简单解决方案:一个简单的解决方案是生成所有子数组,并对所有子数组的AND值求和。平均来说,找到子数组的AND值将花费线性时间,因此,总的时间复杂度将为O(n 3 )。

高效的解决方案:为了更好地理解,我们假定元素的任何位都由变量’i’表示,并且变量’sum’用于存储最终和。

这里的想法是,我们将尝试找到第i位设置为AND的数量(按位与(&)的子数组)。让我们假设,存在i位设置为’S i ‘的子阵列。对于,i位,总和可以更新为总和+ =(2 i * S)。

我们会将任务分为多个步骤。在每一步中,我们将尝试找到第i位设置为AND的数量。为此,我们将简单地遍历数组并找到设置有i位并具有长度的连续段的数量。对于每个这样的长度为“ l”的段,sum的值可以更新为sum + =(2 i * l *(l + 1))/ 2。

由于对于每个位,我们正在执行O(N)次迭代,并且由于最多有log(max(A))个位,因此,假设该方法的时间复杂度为O(N * log(max(A)) max(A)=数组中的最大值。

下面是上述想法的实现:

C++
// CPP program to find sum of bitwise AND
// of all subarrays
  
#include 
#include 
using namespace std;
  
// Function to find the sum of
// bitwise AND of all subarrays
int findAndSum(int arr[], int n)
{
    // variable to store
    // the final sum
    int sum = 0;
  
    // multiplier
    int mul = 1;
  
    for (int i = 0; i < 30; i++) {
        // variable to check if
        // counting is on
        bool count_on = 0;
  
        // variable to store the
        // length of the subarrays
        int l = 0;
  
        // loop to find the contiguous
        // segments
        for (int j = 0; j < n; j++) {
            if ((arr[j] & (1 << i)) > 0)
                if (count_on)
                    l++;
                else {
                    count_on = 1;
                    l++;
                }
  
            else if (count_on) {
                sum += ((mul * l * (l + 1)) / 2);
                count_on = 0;
                l = 0;
            }
        }
  
        if (count_on) {
            sum += ((mul * l * (l + 1)) / 2);
            count_on = 0;
            l = 0;
        }
  
        // updating the multiplier
        mul *= 2;
    }
  
    // returning the sum
    return sum;
}
  
// Driver Code
int main()
{
  
    int arr[] = { 7, 1, 1, 5 };
  
    int n = sizeof(arr) / sizeof(arr[0]);
  
    cout << findAndSum(arr, n);
  
    return 0;
}


Java
// Java program to find sum of bitwise AND
// of all subarrays
class GFG
{
      
// Function to find the sum of
// bitwise AND of all subarrays
static int findAndSum(int []arr, int n)
{
    // variable to store
    // the final sum
    int sum = 0;
  
    // multiplier
    int mul = 1;
  
    for (int i = 0; i < 30; i++) 
    {
        // variable to check if
        // counting is on
        boolean count_on = false;
  
        // variable to store the
        // length of the subarrays
        int l = 0;
  
        // loop to find the contiguous
        // segments
        for (int j = 0; j < n; j++) 
        {
            if ((arr[j] & (1 << i)) > 0)
                if (count_on)
                    l++;
                else
                {
                    count_on = true;
                    l++;
                }
  
            else if (count_on)
            {
                sum += ((mul * l * (l + 1)) / 2);
                count_on = false;
                l = 0;
            }
        }
  
        if (count_on) 
        {
            sum += ((mul * l * (l + 1)) / 2);
            count_on = false;
            l = 0;
        }
  
        // updating the multiplier
        mul *= 2;
    }
  
    // returning the sum
    return sum;
}
  
// Driver Code
public static void main(String[] args)
{
    int []arr = { 7, 1, 1, 5 };
    int n = arr.length;
  
    System.out.println(findAndSum(arr, n));
}
}
  
// This code is contributed 
// by Code_Mech.


Python3
# Python3 program to find Sum of 
# bitwise AND of all subarrays
import math as mt
  
# Function to find the Sum of
# bitwise AND of all subarrays
def findAndSum(arr, n):
      
    # variable to store the final Sum
    Sum = 0
  
    # multiplier
    mul = 1
  
    for i in range(30):
          
        # variable to check if counting is on
        count_on = 0
  
        # variable to store the length
        # of the subarrays
        l = 0
  
        # loop to find the contiguous
        # segments
        for j in range(n):
  
            if ((arr[j] & (1 << i)) > 0):
                if (count_on):
                    l += 1
                else:
                    count_on = 1
                    l += 1
  
            elif (count_on):
                Sum += ((mul * l * (l + 1)) // 2)
                count_on = 0
                l = 0
              
        if (count_on): 
            Sum += ((mul * l * (l + 1)) // 2)
            count_on = 0
            l = 0
          
        # updating the multiplier
        mul *= 2
      
    # returning the Sum
    return Sum
  
# Driver Code
arr = [7, 1, 1, 5]
  
n = len(arr)
  
print(findAndSum(arr, n))
  
# This code is contributed by Mohit Kumar


C#
// C# program to find sum of bitwise AND
// of all subarrays
using System;
  
class GFG
{
  
// Function to find the sum of
// bitwise AND of all subarrays
static int findAndSum(int []arr, int n)
{
    // variable to store
    // the final sum
    int sum = 0;
  
    // multiplier
    int mul = 1;
  
    for (int i = 0; i < 30; i++) 
    {
        // variable to check if
        // counting is on
        bool count_on = false;
  
        // variable to store the
        // length of the subarrays
        int l = 0;
  
        // loop to find the contiguous
        // segments
        for (int j = 0; j < n; j++) 
        {
            if ((arr[j] & (1 << i)) > 0)
                if (count_on)
                    l++;
                else
                {
                    count_on = true;
                    l++;
                }
  
            else if (count_on)
            {
                sum += ((mul * l * (l + 1)) / 2);
                count_on = false;
                l = 0;
            }
        }
  
        if (count_on) 
        {
            sum += ((mul * l * (l + 1)) / 2);
            count_on = false;
            l = 0;
        }
  
        // updating the multiplier
        mul *= 2;
    }
  
    // returning the sum
    return sum;
}
  
// Driver Code
public static void Main()
{
    int []arr = { 7, 1, 1, 5 };
    int n = arr.Length;
  
    Console.Write(findAndSum(arr, n));
}
}
  
// This code is contributed 
// by Akanksha Rai


PHP
 0) 
                if ($count_on) 
                    $l++; 
                else 
                { 
                    $count_on = 1; 
                    $l++; 
                } 
  
            else if ($count_on) 
            { 
                $sum += (($mul * $l * ($l + 1)) / 2); 
                $count_on = 0; 
                $l = 0; 
            } 
        } 
  
        if ($count_on) 
        { 
            $sum += (($mul * $l * ($l + 1)) / 2); 
            $count_on = 0; 
            $l = 0; 
        } 
  
        // updating the multiplier 
        $mul *= 2; 
    } 
  
    // returning the sum 
    return $sum; 
} 
  
// Driver Code 
$arr = array( 7, 1, 1, 5 ); 
  
$n = sizeof($arr); 
  
echo findAndSum($arr, $n); 
  
// This code is contributed by Ryuga
?>


输出:
20

时间复杂度:O(N * log(max(A))