2013ACM/ICPC亚洲区南京站现场赛——题目重现 (HDU 4810) 二进制思想

Wall Painting

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


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
 


【理解】

第k天 取 k 个数 亦或,  结果 加起来 作为第 k 的 答案,

立即想到 组合数,  杨辉三角;

单纯模拟的话, 不好模拟,  k 越大  取得数越多, 不知道 取哪一个;

想了下,  亦或性质,  遇到亦或的 题 总能跟二进制扯上关系,   亦或 1 0  才取 1   1 的个数 只有在 奇数 才会有贡献;

1     0001

2     0010

      10     1010

         1    0001                   1 0 2 2     用 组合数理解为,   转换成十进制,  k=1:   C(3,3) * C (1 .1)* 2^3  +   C(2,1)*(2,0) *2 ^1  +  C(2,1)*C(2,0)* 2^1  ==14




【代码】

注意 运算乘法 会爆 int  用long long int

//#include <bits/stdc++.h>
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cmath>
#include <math.h>
#include <cstring>
#include <string>
#include <queue>
#include <deque>
#include <stack>
#include <stdlib.h>
#include <list>
#include <map>
#include <set>
#include <bitset>
#include <vector>
#define mem(a,b) memset(a,b,sizeof(a))
#define findx(x) lower_bound(b+1,b+1+bn,x)-b
#define FIN      freopen("input.txt","r",stdin)
#define FOUT     freopen("output.txt","w",stdout)
#define S1(n)    scanf("%d",&n)
#define SL1(n)   scanf("%I64d",&n)
#define S2(n,m)  scanf("%d%d",&n,&m)
#define SL2(n,m)  scanf("%I64d%I64d",&n,&m)
#define Pr(n)     printf("%d\n",n)
#define lson rt << 1, l, mid
#define rson rt << 1|1, mid + 1, r

using namespace std;
typedef long long ll;
const double PI=acos(-1);
const int INF=0x3f3f3f3f;
const double esp=1e-6;
const int maxn=1e6+5;
const int MAXN=50005;
const int MOD=1e6+3;
const int mod=1e6+3;
int dir[5][2]={0,1,0,-1,1,0,-1,0};

ll inv[maxn*2];
inline void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){ x=1; y=0; d=a; }else{ ex_gcd(b,a%b,d,y,x); y-=x*(a/b);};}
inline ll gcd(ll a,ll b){ return b?gcd(b,a%b):a;}
inline ll exgcd(ll a,ll b,ll &x,ll &y){if(!b){x=1;y=0;return a;}ll ans=exgcd(b,a%b,x,y);ll temp=x;x=y;y=temp-a/b*y;return ans;}
inline ll lcm(ll a,ll b){ return b/gcd(a,b)*a;}
inline ll qpow(ll x,ll n){ll res=1;for(;n;n>>=1){if(n&1)res=(res*x)%MOD;x=(x*x)%MOD;}return res;}
inline ll inv_exgcd(ll a,ll n){ll d,x,y;ex_gcd(a,n,d,x,y);return d==1?(x+n)%n:-1;}
inline ll inv1(ll b){return b==1?1:(MOD-MOD/b)*inv1(MOD%b)%MOD;}
inline ll inv2(ll b){return qpow(b,MOD-2);}

int c[3010][3010];
void init()
{
    c[0][0]=1;
    for(int i=1;i<=1000;i++)
        for(int j=0;j<=i;j++)
        {
            c[i][j]= ((j==0)? 1: (c[i-1][j]+c[i-1][j-1])%mod);
        }

}
int ans[MAXN];
int num[64];
int main()
{
    int N;
    init();
    while(~scanf("%d",&N))
    {
        mem(ans,0);
        mem(num,0);
        int x;
        for(int i=1;i<=N;i++)
        {
             scanf("%d",&x);
             for(int i=0;i<=30;i++)
                //if( (1<<(i-1))&x )// 统计1 的个数
                  if( (x>>i)&1)
                    num[i]++;
        }
        for(int i=1;i<=N;i++)
        {
            for(int j=0;j<=30;j++)
                for(int k=1;k<=num[j]&&k<=i;k+=2)// 奇数贡献
                {
                    //printf("%d  %d  %d \n",c[num[j]][k],c[N-num[j]][i-k],1<<j);
                    ans[i]= (ans[i] + (ll) (((1<<j)%mod)*(ll)c[num[j]][k]%mod )*(ll)c[N-num[j]][i-k]%mod)%mod;
                }

        }
        printf("%d",ans[1]%mod);
        for(int i=2;i<=N;i++)
            printf(" %d",ans[i]%mod);
        printf("\n");
    }

    return 0;
}


123

posted @ 2017-11-08 13:01  Sizaif  阅读(130)  评论(0编辑  收藏  举报