给定一个由N个非负整数组成的数组A,求出该数组所有无序三元组的xor之和。对于无序三元组,认为三元组(A [i],A [j],A [k])与三元组(A [j],A [i],A [k])和所有其他排列相同。
由于答案可能很大,请使用10037计算其mod。
例子:
Input : A = [3, 5, 2, 18, 7]
Output : 132
Input : A = [140, 1, 66]
Output : 207
天真的方法
遍历所有无序三元组,然后将每个三元组的xor相加。
高效方法
- 需要注意的重要一点是,xor在所有位上都是独立的。因此,我们可以分别对每个位进行所需的计算。
- 让我们考虑所有数组元素的第k位。如果第k个位的x等于1的无整数三元组的数量为C,我们可以简单地将C * 2 k加到答案中。令第k位为1的元素数为X,第k位为0的元素数为Y。然后,可以找到两种情况形成第k位xor等于1的无序三元组:
- 这三个元素中只有一个具有第k位1。
- 他们三个都具有第k位1。
- 选择具有第k个比特的3个元素的方式数目1 =
- 选择第k个比特为1的元素并剩下0 =的方式的数目
- 我们将使用nCr mod p来计算组合函数值。
下面是上述方法的实现。
C++
// C++ program to find sum of xor of
// all unordered triplets of the array
#include
using namespace std;
// Iterative Function to calculate
// (x^y)%p in O(log y)
int power(int x, int y, int p)
{
// Initialize result
int res = 1;
// Update x if it is more than or
// equal to p
x = x % p;
while (y > 0)
{
// If y is odd, multiply x
// with result
if (y & 1)
res = (res * x) % p;
// y must be even now
y = y >> 1; // y = y/2
x = (x * x) % p;
}
return res;
}
// Returns n^(-1) mod p
int modInverse(int n, int p)
{
return power(n, p - 2, p);
}
// Returns nCr % p using Fermat's little
// theorem.
int nCrModPFermat(int n, int r, int p)
{
// Base case
if (r == 0)
return 1;
if (n < r)
return 0;
// Fill factorial array so that we
// can find all factorial of r, n
// and n-r
int fac[n + 1];
fac[0] = 1;
for (int i = 1; i <= n; i++)
fac[i] = fac[i - 1] * i % p;
return (fac[n] * modInverse(fac[r], p) % p
* modInverse(fac[n - r], p) % p) % p;
}
// Function returns sum of xor of all
// unordered triplets of the array
int SumOfXor(int a[], int n)
{
int mod = 10037;
int answer = 0;
// Iterating over the bits
for (int k = 0; k < 32; k++)
{
// Number of elements whith k'th bit
// 1 and 0 respectively
int x = 0, y = 0;
for (int i = 0; i < n; i++)
{
// Checking if k'th bit is 1
if (a[i] & (1 << k))
x++;
else
y++;
}
// Adding this bit's part to the answer
answer += ((1 << k) % mod *
(nCrModPFermat(x, 3, mod)
+ x * nCrModPFermat(y, 2, mod))
% mod) % mod;
}
return answer;
}
// Drivers code
int main()
{
int n = 5;
int A[n] = { 3, 5, 2, 18, 7 };
cout << SumOfXor(A, n);
return 0;
}
Java
// Java program to find sum of xor of
// all unordered triplets of the array
class GFG{
// Iterative Function to calculate
// (x^y)%p in O(log y)
static int power(int x, int y, int p)
{
// Initialize result
int res = 1;
// Update x if it is more than or
// equal to p
x = x % p;
while (y > 0)
{
// If y is odd, multiply x
// with result
if ((y & 1) == 1)
res = (res * x) % p;
// y must be even now
y = y >> 1; // y = y/2
x = (x * x) % p;
}
return res;
}
// Returns n^(-1) mod p
static int modInverse(int n, int p)
{
return power(n, p - 2, p);
}
// Returns nCr % p using Fermat's little
// theorem.
static int nCrModPFermat(int n, int r, int p)
{
// Base case
if (r == 0)
return 1;
if (n < r)
return 0;
// Fill factorial array so that we
// can find all factorial of r, n
// and n-r
int fac[] = new int[n + 1];
fac[0] = 1;
for(int i = 1; i <= n; i++)
fac[i] = fac[i - 1] * i % p;
return (fac[n] * modInverse(fac[r], p) % p *
modInverse(fac[n - r], p) %
p) % p;
}
// Function returns sum of xor of all
// unordered triplets of the array
static int SumOfXor(int a[], int n)
{
int mod = 10037;
int answer = 0;
// Iterating over the bits
for(int k = 0; k < 32; k++)
{
// Number of elements whith k'th bit
// 1 and 0 respectively
int x = 0, y = 0;
for(int i = 0; i < n; i++)
{
// Checking if k'th bit is 1
if ((a[i] & (1 << k)) != 0)
x++;
else
y++;
}
// Adding this bit's part to the answer
answer += ((1 << k) % mod *
(nCrModPFermat(x, 3, mod) + x *
nCrModPFermat(y, 2, mod)) %
mod) % mod;
}
return answer;
}
// Driver code
public static void main(String[] args)
{
int n = 5;
int A[] = { 3, 5, 2, 18, 7 };
System.out.println(SumOfXor(A, n));
}
}
// This code is contributed by jrishabh99
Python3
# Python3 program to find sum of xor of
# all unordered triplets of the array
# Iterative Function to calculate
# (x^y)%p in O(log y)
def power(x, y, p):
# Initialize result
res = 1
# Update x if it is more than or
# equal to p
x = x % p
while (y > 0):
# If y is odd, multiply x
# with result
if (y & 1):
res = (res * x) % p
# y must be even now
y = y >> 1#y = y/2
x = (x * x) % p
return res
# Returns n^(-1) mod p
def modInverse(n, p):
return power(n, p - 2, p)
# Returns nCr % p using Fermat's little
# theorem.
def nCrModPFermat(n, r, p):
# Base case
if (r == 0):
return 1
if (n < r):
return 0
# Fill factorial array so that we
# can find all factorial of r, n
# and n-r
fac = [0]*(n + 1)
fac[0] = 1
for i in range(1, n + 1):
fac[i] = fac[i - 1] * i % p
return (fac[n] * modInverse(fac[r], p) % p *
modInverse(fac[n - r], p) % p) % p
# Function returns sum of xor of all
# unordered triplets of the array
def SumOfXor(a, n):
mod = 10037
answer = 0
# Iterating over the bits
for k in range(32):
# Number of elements whith k'th bit
# 1 and 0 respectively
x = 0
y = 0
for i in range(n):
# Checking if k'th bit is 1
if (a[i] & (1 << k)):
x += 1
else:
y += 1
# Adding this bit's part to the answer
answer += ((1 << k) % mod * (nCrModPFermat(x, 3, mod)
+ x * nCrModPFermat(y, 2, mod))
% mod) % mod
return answer
# Drivers code
if __name__ == '__main__':
n = 5
A=[3, 5, 2, 18, 7]
print(SumOfXor(A, n))
# This code is contributed by mohit kumar 29
C#
// C# program to find sum of xor of
// all unordered triplets of the array
using System;
class GFG{
// Iterative Function to calculate
// (x^y)%p in O(log y)
static int power(int x, int y, int p)
{
// Initialize result
int res = 1;
// Update x if it is more than or
// equal to p
x = x % p;
while (y > 0)
{
// If y is odd, multiply x
// with result
if ((y & 1) == 1)
res = (res * x) % p;
// y must be even now
y = y >> 1; // y = y/2
x = (x * x) % p;
}
return res;
}
// Returns n^(-1) mod p
static int modInverse(int n, int p)
{
return power(n, p - 2, p);
}
// Returns nCr % p using Fermat's little
// theorem.
static int nCrModPFermat(int n, int r, int p)
{
// Base case
if (r == 0)
return 1;
if (n < r)
return 0;
// Fill factorial array so that we
// can find all factorial of r, n
// and n-r
int []fac = new int[n + 1];
fac[0] = 1;
for(int i = 1; i <= n; i++)
fac[i] = fac[i - 1] * i % p;
return (fac[n] * modInverse(fac[r], p) % p *
modInverse(fac[n - r], p) %
p) % p;
}
// Function returns sum of xor of all
// unordered triplets of the array
static int SumOfXor(int []a, int n)
{
int mod = 10037;
int answer = 0;
// Iterating over the bits
for(int k = 0; k < 32; k++)
{
// Number of elements whith k'th bit
// 1 and 0 respectively
int x = 0, y = 0;
for(int i = 0; i < n; i++)
{
// Checking if k'th bit is 1
if ((a[i] & (1 << k)) != 0)
x++;
else
y++;
}
// Adding this bit's part to the answer
answer += ((1 << k) % mod *
(nCrModPFermat(x, 3, mod) + x *
nCrModPFermat(y, 2, mod)) %
mod) % mod;
}
return answer;
}
// Driver code
public static void Main(String[] args)
{
int n = 5;
int []A = { 3, 5, 2, 18, 7 };
Console.WriteLine(SumOfXor(A, n));
}
}
// This code is contributed by gauravrajput1
输出:
132
时间复杂度: O(32 * N)