HDU 4810 Wall Painting

Wall Painting

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1026    Accepted Submission(s): 280


Problem Description
Ms.Fang loves painting very much. She paints GFW(Great Funny Wall) every day. Every day before painting, she produces a wonderful color of pigments by mixing water and some bags of pigments. On the K-th day, she will select K specific bags of pigments and mix them to get a color of pigments which she will use that day. When she mixes a bag of pigments with color A and a bag of pigments with color B, she will get pigments with color A xor B.
When she mixes two bags of pigments with the same color, she will get color zero for some strange reasons. Now, her husband Mr.Fang has no idea about which K bags of pigments Ms.Fang will select on the K-th day. He wonders the sum of the colors Ms.Fang will get with different plans.

For example, assume n = 3, K = 2 and three bags of pigments with color 2, 1, 2. She can get color 3, 3, 0 with 3 different plans. In this instance, the answer Mr.Fang wants to get on the second day is 3 + 3 + 0 = 6.
Mr.Fang is so busy that he doesn’t want to spend too much time on it. Can you help him?
You should tell Mr.Fang the answer from the first day to the n-th day.
 

 

Input
There are several test cases, please process till EOF.
For each test case, the first line contains a single integer N(1 <= N <= 103).The second line contains N integers. The i-th integer represents the color of the pigments in the i-th bag.
 

 

Output
For each test case, output N integers in a line representing the answers(mod 106 +3) from the first day to the n-th day.
 

 

Sample Input
4
1 2 10 1
 

 

Sample Output
14 36 30 8
题意:每次从n个数字中取出i个数字,取出的这些数字亦或后得到一个值,每种情况的值求和。i 从1--n。
        其实就是cnm,的数字亦或的和。
思路:看了别人的题解才知道巧妙的地方。
如果我们把数字转换为二进制数,然后统计每位1的个数。
  我们知道,如果我们取出的数字中,对于二进制的第i位来说,假如1的个数为偶数个,那么这一位就是为0了。
                              假如是奇数个,那么就是1。
这样我们就是知道每位的1的个数和0 的个数,cnm,凑成奇数个1.
看对于第i位来说凑成奇数个1的方案数有多少,记位num[ i ]。
那么对于第i位而已,和就是num[i] *(1<<i) ;
 
代码:
 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<cstring>
 4 #include<cstdlib>
 5 using namespace std;
 6 typedef __int64 LL;
 7 
 8 const LL p = 1e6+3;
 9 int a[66];
10 LL cnm[1002][1002];
11 LL hxl[66];
12 
13 void Init()
14 {
15     for(int i=1;i<=1000;i++)
16     {
17         cnm[i][i]= 1;
18         cnm[i][1]= i;
19         cnm[i][0]=1;
20     }
21     cnm[0][0]=1;
22     for(int i=2;i<=1000;i++)
23     {
24         for(int j=1;j<=i;j++)
25         {
26             if(i==j)cnm[i][j]=1;
27             else if(j==1) cnm[i][j]=i;
28             else cnm[i][j] = (cnm[i-1][j]+cnm[i-1][j-1])%p;
29         }
30     }
31     hxl[1]=1;
32     for(int i=2;i<=64;i++)
33         hxl[i]=(hxl[i-1]*2)%p;
34 }
35 int main()
36 {
37     Init();
38     int n;
39     LL x;
40     while(scanf("%d",&n)>0)
41     {
42         if(n==1)
43         {
44             scanf("%I64d",&x);
45             printf("%I64d\n",x%p);
46             continue;
47         }
48         memset(a,0,sizeof(a));
49         for(int i=1;i<=n;i++)
50         {
51             scanf("%I64d",&x);
52             int len = 0;
53             while(x)
54             {
55                 ++len;
56                 a[len] = a[len]+(x&1);
57                 x=x>>1;
58             }
59         }
60         LL sum ;
61         for(int m=1;m<=n;m++)//枚举一次取几个数字
62         {
63             sum = 0;
64             for(int j=1;j<=64;j++)//枚举每一个位
65             {
66                 for(int i=1;i<=a[j]&&i<=m;i=i+2)//每一位上取1的个数
67                 {
68                     //if(cnm[n-a[j]][m-i])
69                     sum = (sum+(hxl[j]*(cnm[a[j]][i]*cnm[n-a[j]][m-i])%p)%p)%p;
70                 }
71             }
72             printf("%I64d",sum);
73             if(m!=n) printf(" ");
74             else printf("\n");
75         }
76     }
77     return 0;
78 }

 

posted @ 2014-09-17 10:17  芷水  阅读(218)  评论(0编辑  收藏  举报