题意:求n个数里面,取k个数异或的所有组合(Cn,k种)的和,k取1~n
思路:枚举k,因为是异或,所以看二进制,最后的和的每一位二进制的值为n个数这一位的二进制取k个时1的个数为
奇数的方案数,那怎么计算n个0或1的数中取k个,取到的1的个数为奇数呢,比如有num1个1,num0个0,那么取k个
的方案中取出的是奇数个1的方案数位C(num1,1)*C(num0, k-1)+C(num1, 3)*C(num0, k-3)...
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e6+3;
const int maxn = 1e3+5;
ll a[maxn], c[maxn][maxn], n;
ll fac[maxn] = {1};
ll rec[maxn], b[maxn];
ll ans[maxn];
void init()
{
c[0][0] = 1;
for(int i = 1; i < maxn; i++)
for(int j = 0; j <= i; j++)
{
if(!j || i == j)
c[i][j] = 1;
else
c[i][j] = (c[i-1][j]+c[i-1][j-1])%mod;
}
for(int i = 1; i < maxn; i++)
fac[i] = fac[i-1]*2%mod;
}
void solve(int k)
{
memset(rec, 0, sizeof(rec));
int num0 = 0, num1 = 0;
for(int i = 1; i <= n; i++)
b[i] = a[i];
for(int i = 0; i < 33; i++)
{
num1 = num0 = 0;
for(int j = 1; j <= n; j++)
{
int idx = b[j]%2;
if(idx) num1++;
else num0++;
b[j] /= 2;
}
for(int j = 1; j <= k; j += 2)
rec[i] = (rec[i]+c[num1][j]*c[num0][k-j]%mod)%mod;
}
ll res = 0;
for(int i = 0; i < 33; i++)
res = (res+rec[i]*fac[i]%mod)%mod;
ans[k] = res;
}
int main(void)
{
init();
while(cin >> n)
{
for(int i = 1; i <= n; i++)
scanf("%lld", &a[i]);
for(int i = 1; i <= n; i++)
solve(i);
for(int i = 1; i <= n; i++)
printf("%lld%c", ans[i], i==n ? '\n' : ' ');
}
return 0;
}
/*
4
1 2 10 1
*/