📌  相关文章
📜  所有可能子集的异或之和

📅  最后修改于: 2022-05-13 01:57:51.591000             🧑  作者: Mango

所有可能子集的异或之和

给定一个大小为 n 的数组 arr[],我们需要找到来自对子集的所有元素进行异或的所有值的总和。

Input :  arr[] = {1, 5, 6}
Output : 28
Total Subsets = 23
1 = 1
5 = 5
6 = 6
1 ^ 5 = 4
1 ^ 6 = 7
5 ^ 6 = 3
1 ^ 5 ^ 6 = 2
0(empty subset)
Now SUM of all these XORs = 1 + 5 + 6 + 4 +
                            7 + 3 + 2 + 0
                          = 28

Input : arr[] = {1, 2}
Output : 6
 

一种简单的方法是对 array[] 元素的所有可能组合进行异或运算,然后对所有值进行求和。这种方法的时间复杂度呈指数增长,因此对于较大的 n 值不会更好。
一种有效的方法是根据 XOR 的属性找到模式。现在再次考虑二进制形式的子集,例如:

1 = 001
    5 = 101
    6 = 110
1 ^ 5 = 100
1 ^ 6 = 111
5 ^ 6 = 011
1^5^6 = 010

因此,如果我们分析所有这些 XOR 的二进制数,我们可以观察到在 i(0 到 n-1) 的所有位置出现的设置位将恰好有助于 2 n的一半。所以我们可以很容易地在 i 的每个这样的位置上强加这两个条件。

  • 如果 arr[] 的任何值设置了第 i位集,则 2 n个子集的恰好一半将具有这种形式,因此它们将有助于 2 n-1+i到最终总和。
  • 如果没有设置i 位的 arr[] 的值,那么我们可以说在所有设置了第 i位的子集中都没有项。

上述观点的证明如下:
情况1:
让我们假设数组中有 k 个元素设置了第 i位,并且 k 不为零。
因此,要在其 xor 中设置第 i 位的子集,我们需要它具有奇数个具有第i位设置的元素。
选择第 i位未设置的元素的方法数 = 2 (nk)
选择第 i位集合的元素的方法数 = k C 1 + k C 3 + k C 5 ...。 = 2 (k-1)
总路数 = 2 (n-1)
因此,对 sum 的贡献变为 2 (n+i-1)
案例二:
如果没有元素设置第 i位,即 k = 0,则第 i位对总和的贡献保持为 0。
现在问题归结为检查 arr[] 元素的哪个位置将被设置。但是这里有一些技巧,我们不会一个一个地迭代所有元素,尽管我们可以简单地对所有这些值进行 OR 并乘以 2 n-1 ,例如:-

Take a OR of all arr[] elements, we get 
= 1 | 5 | 6
= 001 | 101 | 110
= 111

Now to find final summation, we can write it down as:-
= 1*2n-1+2 + 1*2n-1+1 + 1*2n-1+0
= 2n-1 * (1*22 + 1*21 + 1*20 )
= 2n-1 * (1112)
= 2n-1 * 7

Put n = 3,  we get
= 28

所以最后对于 n 和数组元素的任何值,我们可以简单地说最终总和将是所有输入的按位 OR 的 2 n-1倍。

C++
// Below is C++ approach to finding the XOR_SUM
#include
using namespace std;
 
// Returns sum of XORs of all subsets
int xorSum(int arr[], int n)
{
    int bits = 0;
 
    // Finding bitwise OR of all elements
    for (int i=0; i < n; ++i)
        bits |= arr[i];
 
    int ans = bits * pow(2, n-1);
 
    return ans;
}
 
// Driver code
int main()
{
    int arr[] = {1, 5, 6};
    int size = sizeof(arr) / sizeof(arr[0]);
    cout << xorSum(arr, size);
}


Java
// Java approach to finding the XOR_SUM
class GFG {
     
    // Returns sum of XORs of all subsets
    static int xorSum(int arr[], int n)
    {
         
        int bits = 0;
     
        // Finding bitwise OR of all elements
        for (int i = 0; i < n; ++i)
            bits |= arr[i];
     
        int ans = bits * (int)Math.pow(2, n-1);
     
        return ans;
    }
     
    // Driver method
    public static void main(String[] args)
    {
         
        int arr[] = {1, 5, 6};
        int size = arr.length;
         
        System.out.print(xorSum(arr, size));
    }
}
 
// This code is contributed by Anant Agarwal.


Python3
# Python3 approach to finding the XOR_SUM
 
# Returns sum of XORs of all subsets
def xorSum(arr, n):
 
    bits = 0
 
    # Finding bitwise OR of all elements
    for i in range(n):
        bits |= arr[i]
 
    ans = bits * pow(2, n-1)
 
    return ans
 
# Driver Code
arr = [1, 5, 6]
size = len(arr)
print(xorSum(arr, size))
 
# This code is contributed by Anant Agarwal.


C#
// C# approach to finding the XOR_SUM
using System;
 
class GFG {
     
    // Returns sum of XORs of all subsets
    static int xorSum(int []arr, int n)
    {
         
        int bits = 0;
     
        // Finding bitwise OR of all elements
        for (int i = 0; i < n; ++i)
            bits |= arr[i];
     
        int ans = bits * (int)Math.Pow(2, n - 1);
     
        return ans;
    }
     
    // Driver code
    public static void Main()
    {
         
        int []arr = {1, 5, 6};
        int size = arr.Length;
         
        Console.Write(xorSum(arr, size));
    }
}
 
// This code is contributed by Nitin Mittal.


PHP


Javascript


输出:

28