HDU 4810 Wall Painting(异或 组合数)

来源:互联网 发布:阿里云ecs推荐码 编辑:程序博客网 时间:2024/05/21 15:39

题意:求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;}/*41 2 10 1*/



原创粉丝点击