HDU4810 Wall Painting

本文探讨了在特定数值集合中,通过异或运算进行组合的数学原理及应用,详细解释了如何利用组合数学计算不同数量元素异或后的所有可能结果。

题意:就是在n个数里,取1个异或起来的所有情况加起来,取2个值异或起来的所有值加起来,一直到取n个值异或的情况加起来,输出1-n的所有答案。。

把每个数都用2进制表示出来,然后统计每个数位上1的个数,然后就是取k个数在上面异或,所以有奇数个1异或起来就是1,偶数个就是0,组合数算下就好。

/*************************************************************************
	> File Name: 4810.cpp
	> Author: tjw
	> Mail:
	> Created Time: 2014年11月09日 星期日 16时14分49秒
 ************************************************************************/

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<stack>
#include<map>
#define ll long long
#define ls k<<1
#define rs k<<1|1
using namespace std;
const int MAXN=32;
const int MOD=1000003;
int a[32],b[32];
long long c[1010][1010];
int top;
void doit(int x)
{
    int k=0;
    while(x)
    {
        a[k++]+=x%2;
        x>>=1;
    }
    if(k>top)
        top=k;
}
int main()
{
    int i,j,n,x,k;
    memset(c,0,sizeof(c));
    c[0][0]=1;
    for(i=1;i<=1000;i++)
    {
        c[i][0]=1;
        for(j=1;j<=i;j++)
         {
                 c[i][j]=(c[i-1][j-1]+c[i-1][j])%MOD;
         }
    }
    while(scanf("%d",&n)==1)
    {
        memset(a,0,sizeof(a));
        top=0;
        for(i=0;i<n;i++)
        {
            scanf("%d",&x);
            doit(x);
        }
        for(i=0;i<top;i++)
                b[i]=n-a[i];
        for(i=1;i<=n;i++)
        {
            int ans=0;
            for(j=0;j<top;j++)
            {
                for(k=1;k<=i;k+=2)
                {
                    int zero=i-k;
                    if(k>a[j])
                        break;
                    if(zero>b[j])
                        continue;
                    ll temp=(c[a[j]][k]*c[b[j]][zero])%MOD;
                    int temp1=(temp<<j)%MOD;	//temp要是64位的才不会爆。。。。
                    ans=(ans+temp1)%MOD;
                }
            }
            if(i<n)
                printf("%d ",ans);
            else
                printf("%d\n",ans);
        }
    }
    return 0;
}


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值