/*
hdu 4810
题意就是给你一个数n,再给你n个数
然后依次求
1个数的异或和
2个数的异或和
一直到n个数
看了题解后发现可以利用
异或的这个性质
奇数个1就是1
偶数个1就是0
所以我们可以把每一位拆开
来看是否有值
最后再求和
比如样例
1 2 10 1
这四个数的二进制分别为
0 0 0 1
0 0 1 0
1 0 1 0
0 0 0 1
比如第2天的时候
从4个中选出2个来做异或
第4位上只有1个1
所以有3中选法可以使得这一位异或之后结果为1
(也就是C(3,1) * C(1,1))
第3位的没有1
所以异或结果一定为0
第2位上又2个1
所以有4种选法
同理第一位上也是4种
所以其结果就是
(1<<3)*C(3,1)+0*C(4,2)+(1<<1)*C(2,1)*C(2,1)+(1<<0)*C(2,1)*C(2,1)
用字母整理下就是
设这一位是2^i,有m个1,今天为第j天,选中了k个1(k为奇数且小于等于j、m)
则方案数为C(m,k)*C(n-m,j-k) (这只表示第i项是1有多少种情况)
最后求和sum+=2^i*C(m,k)*C(n-m,j-k) (情况数乘以这一项表示的值,就是这一项表示的权值,再把所有权值相加即可)
PS:题目还要对1000003取余
*/
#include <iostream>
#include <stdio.h>
#include <string.h>
#define ll long long
#define mod 1000003
using namespace std;
ll c[1010][1010];
void init()//对组合数打表
{
memset(c,0,sizeof(0));
c[0][0]=1;
for(int i=1;i<=1000;i++)
{
for(int j=0;j<=1000;j++)
{
if(j==0)
c[i][j]=1;
else
c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
}
}
}
int main()
{
init();
int n;
while(cin>>n)
{
int a[1010];
memset(a,0,sizeof(a));
for(int i=1;i<=n;i++)//记录下每一项有多少个1,因为每一项不是1就是0,所以0的个数就是n减去1的个数
{
int res;
cin>>res;
for(int j=1;res>0;j++,res=res>>1)
a[j]+=res&1;//如果res这个数这一项是1,那么就加1,否则加0
}
for(int i=1;i<=n;i++)//异或个数
{
ll sum=0;
for(int j=1;j<=32;j++)//第j项
for(int k=1;k<=a[j]&&k<=i;k+=2)//取奇数个的1
sum=((((c[a[j]][k]*c[n-a[j]][i-k])%mod)*(1<<(j-1))%mod)%mod+sum)%mod;
if(i!=1)
cout<<' ';
cout<<sum;
}
cout<<endl;
}
return 0;
}
hdu 4810
题意就是给你一个数n,再给你n个数
然后依次求
1个数的异或和
2个数的异或和
一直到n个数
看了题解后发现可以利用
异或的这个性质
奇数个1就是1
偶数个1就是0
所以我们可以把每一位拆开
来看是否有值
最后再求和
比如样例
1 2 10 1
这四个数的二进制分别为
0 0 0 1
0 0 1 0
1 0 1 0
0 0 0 1
比如第2天的时候
从4个中选出2个来做异或
第4位上只有1个1
所以有3中选法可以使得这一位异或之后结果为1
(也就是C(3,1) * C(1,1))
第3位的没有1
所以异或结果一定为0
第2位上又2个1
所以有4种选法
同理第一位上也是4种
所以其结果就是
(1<<3)*C(3,1)+0*C(4,2)+(1<<1)*C(2,1)*C(2,1)+(1<<0)*C(2,1)*C(2,1)
用字母整理下就是
设这一位是2^i,有m个1,今天为第j天,选中了k个1(k为奇数且小于等于j、m)
则方案数为C(m,k)*C(n-m,j-k) (这只表示第i项是1有多少种情况)
最后求和sum+=2^i*C(m,k)*C(n-m,j-k) (情况数乘以这一项表示的值,就是这一项表示的权值,再把所有权值相加即可)
PS:题目还要对1000003取余
*/
#include <iostream>
#include <stdio.h>
#include <string.h>
#define ll long long
#define mod 1000003
using namespace std;
ll c[1010][1010];
void init()//对组合数打表
{
memset(c,0,sizeof(0));
c[0][0]=1;
for(int i=1;i<=1000;i++)
{
for(int j=0;j<=1000;j++)
{
if(j==0)
c[i][j]=1;
else
c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
}
}
}
int main()
{
init();
int n;
while(cin>>n)
{
int a[1010];
memset(a,0,sizeof(a));
for(int i=1;i<=n;i++)//记录下每一项有多少个1,因为每一项不是1就是0,所以0的个数就是n减去1的个数
{
int res;
cin>>res;
for(int j=1;res>0;j++,res=res>>1)
a[j]+=res&1;//如果res这个数这一项是1,那么就加1,否则加0
}
for(int i=1;i<=n;i++)//异或个数
{
ll sum=0;
for(int j=1;j<=32;j++)//第j项
for(int k=1;k<=a[j]&&k<=i;k+=2)//取奇数个的1
sum=((((c[a[j]][k]*c[n-a[j]][i-k])%mod)*(1<<(j-1))%mod)%mod+sum)%mod;
if(i!=1)
cout<<' ';
cout<<sum;
}
cout<<endl;
}
return 0;
}