-----hdu4810 Wall Painting

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 <= 10 3).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 10 6 +3) from the first day to the n-th day.
Sample Input
4
1 2 10 1
Sample Output
14 36 30 8
题意:给你n个数,从第一天到第n天,第k天的时候,从n个数里面选出k个数亦或,当然会有Cnk种情况,然后把每种情况亦或后的结果累加求和,就是第k天要输出的数

#include <iostream>
#include<stdio.h>
#include <algorithm>
#include <math.h>
#include <string.h>

using namespace std;
const int mod=1e6+3;
long long sum[1010];
int a[1010];
long long c[1015][1015];
void yhui()
{
    c[0][0]=1;
    for(int i=1; i<=1010; i++)
        for(int j=0; j<=i; j++)
        {
             if(j==0||j==i)
                c[i][j]=1;
            else c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
        }
}
void fun(int x)
{
    int k=0;
    while(x!=0)
    {
        a[k]+=x%2;
        k++;
        x=x/2;
    }
}
int main()
{
    yhui();
    int n;
    int data;
    while(cin>>n)
    {
        memset(sum,0,sizeof(sum));
        memset(a,0,sizeof(a));
        //memset(c,0,sizeof(c));
        for(int i=0; i<n; i++)
        {
            cin>>data;
            fun(data);
        }
        for(int i=1; i<=n; i++)///i代表第i天
            for(int j=0; j<32; j++)///32进制,每个数最多就32位,即32列
                for(int k=1; k<=i; k+=2)///选择奇数个1,只有选奇数个1的时候,i个数亦或后那一列的结果才是1,
                    ///不然亦或后结果为0的话,0乘以它的位权还是0,没有任何意义
                {
                    sum[i]+=((c[a[j]][k]*c[n-a[j]][i-k])%mod)*((1<<j)%mod);
                    sum[i]=sum[i]%mod;
                }
        for(int i=1; i<n; i++)
            printf("%lld ",sum[i]);
        printf("%lld\n",sum[n]);
    }
return 0;
}
///一列一列的选///c[a[j]][k]代表从a[j]个1里面选奇数k个1,
                    ///这样才能保证亦或的结果是1,是有效的1数值
                    ///一列n个数不是0就是1,所以应该从n-a[j]个0中选剩下的i-k个数
                    ///c[a[j]][k]*c[n-a[j]][i-k] 这个数值得到的是第j列中,选择i个数,亦或后结果为1的情况有多少种
                    ///假如结果是s,则说明i个数亦或后有s种情况是1,分别每个1乘以它的位权,累加其实就是s个它的位权
                    ///(c[a[j]][k]*c[n-a[j]][i-k]))*pow(2,j) 所以这个代表的就是第i天的时候,第j列中i个数亦或后的二进制结果
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值