给定一个包含 N 个正整数的数组,任务是找到该数组所有子数组的异或之和。
例子:
Input : arr[] = {1, 3, 7, 9, 8, 7}
Output : 128
Input : arr[] = {3, 8, 13}
Output : 46
Explanation for second test-case:
XOR of {3} = 3
XOR of {3, 8} = 11
XOR of {3, 8, 13} = 6
XOR of {8} = 8
XOR of {8, 13} = 5
XOR of {13} = 13
Sum = 3 + 11 + 6 + 8 + 5 + 13 = 46
简单的解决方案:一个简单的解决方案是生成所有子数组,然后遍历它们以找到所需的 XOR 值,然后将它们相加。这种方法的时间复杂度为 O(n 3 )。
更好的解决方案:更好的解决方案是使用前缀数组,即对于数组 ‘arr[]’ 的每个索引 ‘i’,创建一个前缀数组来存储来自数组 ‘arr[] 左端的所有元素的 XOR ]’ 直到 ‘arr[]’ 的第i个元素。创建前缀数组将花费 O(N) 的时间。
现在,使用这个前缀数组,我们可以在 O(1) 时间内找到任何子数组的 XOR 值。
我们可以使用以下公式找到从索引 l 到 r 的 XOR:
if l is not zero
XOR = prefix[r] ^ prefix[l-1]
else
XOR = prefix[r].
在此之后,我们所要做的就是总结所有子数组的异或值。
由于子数组的总数为(N 2 )阶,因此该方法的时间复杂度为 O(N 2 )。
最佳解决方案:为了更好地理解,让我们假设元素的任何位都由变量 ‘i’ 表示,变量 ‘sum’ 用于存储最终和。
这里的想法是,我们将设法找到XOR值的数量与第i位设置。让我们假设,有 ‘S i ‘个设置了第i 位的子阵列。对于第i 位,总和可以更新为sum += (2 i * S) 。
那么,问题是如何实现上述想法呢?
我们将任务分解为多个步骤。在每一步中,我们将设法找到XOR值的数量与第i位设置。
现在,我们将每个步骤分解为子步骤。在每个子步骤中,我们将尝试从索引“j”(其中 j 在 0 到 n – 1 之间变化)开始,并在它们的 XOR 值中设置第i 位,找出子数组的数量。因为,要设置第i 位,子阵列的奇数个元素应该设置第i 位。
对于所有位,在变量 c_odd 中,我们将存储从 j = 0 开始的子数组数量的计数,其中第i 位设置在奇数个元素中。然后,我们将遍历数组的所有元素,在需要时更新 c_odd 的值。如果我们到达第i 位设置的元素“j”,我们将更新 c_odd 为c_odd = (n – j – c_odd) 。其因为,由于我们遇到了一组位,子阵列的与i个元素个比特组将切换到多个子阵列的具有奇数个与i个元素个位组中的偶数数目的数目。
下面是这个方法的实现:
C++
// C++ program to find the sum of XOR of
// all subarray of the array
#include
#include
using namespace std;
// Function to calculate the sum of XOR
// of all subarrays
int findXorSum(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 store number of
// sub-arrays with odd number of elements
// with ith bits starting from the first
// element to the end of the array
int c_odd = 0;
// variable to check the status
// of the odd-even count while
// calculating c_odd
bool odd = 0;
// loop to calculate initial
// value of c_odd
for (int j = 0; j < n; j++) {
if ((arr[j] & (1 << i)) > 0)
odd = (!odd);
if (odd)
c_odd++;
}
// loop to iterate through
// all the elements of the
// array and update sum
for (int j = 0; j < n; j++) {
sum += (mul * c_odd);
if ((arr[j] & (1 << i)) > 0)
c_odd = (n - j - c_odd);
}
// updating the multiplier
mul *= 2;
}
// returning the sum
return sum;
}
// Driver Code
int main()
{
int arr[] = { 3, 8, 13 };
int n = sizeof(arr) / sizeof(arr[0]);
cout << findXorSum(arr, n);
return 0;
}
Java
// Java program to find the sum of XOR
// of all subarray of the array
import java.util.*;
class GFG
{
// Function to calculate the sum of XOR
// of all subarrays
static int findXorSum(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 store number of
// sub-arrays with odd number of elements
// with ith bits starting from the first
// element to the end of the array
int c_odd = 0;
// variable to check the status
// of the odd-even count while
// calculating c_odd
boolean odd = false;
// loop to calculate initial
// value of c_odd
for (int j = 0; j < n; j++)
{
if ((arr[j] & (1 << i)) > 0)
odd = (!odd);
if (odd)
c_odd++;
}
// loop to iterate through
// all the elements of the
// array and update sum
for (int j = 0; j < n; j++)
{
sum += (mul * c_odd);
if ((arr[j] & (1 << i)) > 0)
c_odd = (n - j - c_odd);
}
// updating the multiplier
mul *= 2;
}
// returning the sum
return sum;
}
// Driver code
public static void main(String[] args)
{
int arr[] = { 3, 8, 13 };
int n = arr.length;
System.out.println(findXorSum(arr, n));
}
}
// This code is contributed by Rituraj Jain.
Python3
# Python3 program to find the Sum of
# XOR of all subarray of the array
# Function to calculate the Sum of XOR
# of all subarrays
def findXorSum(arr, n):
# variable to store the final Sum
Sum = 0
# multiplier
mul = 1
for i in range(30):
# variable to store number of sub-arrays
# with odd number of elements with ith
# bits starting from the first element
# to the end of the array
c_odd = 0
# variable to check the status of the
# odd-even count while calculating c_odd
odd = 0
# loop to calculate initial
# value of c_odd
for j in range(n):
if ((arr[j] & (1 << i)) > 0):
odd = (~odd)
if (odd):
c_odd += 1
# loop to iterate through all the
# elements of the array and update Sum
for j in range(n):
Sum += (mul * c_odd)
if ((arr[j] & (1 << i)) > 0):
c_odd = (n - j - c_odd)
# updating the multiplier
mul *= 2
# returning the Sum
return Sum
# Driver Code
arr = [3, 8, 13]
n = len(arr)
print(findXorSum(arr, n))
# This code is contributed by Mohit Kumar
C#
// C# program to find the sum of XOR of
// all subarray of the array
using System;
class GFG
{
// Function to calculate the sum
// of XOR of all subarrays
static int findXorSum(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 store number of sub-arrays
// with odd number of elements with ith
// bits starting from the first element
// to the end of the array
int c_odd = 0;
// variable to check the status
// of the odd-even count while
// calculating c_odd
bool odd = false;
// loop to calculate initial
// value of c_odd
for (int j = 0; j < n; j++)
{
if ((arr[j] & (1 << i)) > 0)
odd = (!odd);
if (odd)
c_odd++;
}
// loop to iterate through
// all the elements of the
// array and update sum
for (int j = 0; j < n; j++)
{
sum += (mul * c_odd);
if ((arr[j] & (1 << i)) > 0)
c_odd = (n - j - c_odd);
}
// updating the multiplier
mul *= 2;
}
// returning the sum
return sum;
}
// Driver Code
static void Main()
{
int []arr = { 3, 8, 13 };
int n = arr.Length;
Console.WriteLine(findXorSum(arr, n));
}
}
// This code is contributed by mits
PHP
0)
$odd = (!$odd);
if ($odd)
$c_odd++;
}
// loop to iterate through
// all the elements of the
// array and update sum
for ($j = 0; $j < $n; $j++)
{
$sum += ($mul * $c_odd);
if (($arr[$j] & (1 << $i)) > 0)
$c_odd = ($n - $j - $c_odd);
}
// updating the multiplier
$mul *= 2;
}
// returning the sum
return $sum;
}
// Driver Code
$arr = array(3, 8, 13);
$n = sizeof($arr);
echo findXorSum($arr, $n);
// This code is contributed by Ryuga
?>
Javascript
46
时间复杂度:O(N)