hdu4810Wall Painting dp+异或

来源:互联网 发布:西安java开发工资 编辑:程序博客网 时间:2024/06/06 12:28
//给出n个数,求出所有从c(n,k)中情况//从这n个数中选出k个的到的所有数异或值之和//dp[j][k][0]  前i个数,选j个数,用二进制表示第k位是0的数的个数//dp[j][k][1]  前i个数,选j个数,用二进制表示第k位是1的数的个数#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std ;const int maxn = 1e3+100 ;typedef unsigned long long  ll ;const ll mod = 1e6+3 ;ll a[maxn] ;int dp[maxn][100][2] ;int main(){    int n ;    while(~scanf("%d" , &n))    {        memset(dp , 0 , sizeof(dp)) ;        for(int i = 1;i <= n;i++)        {            scanf("%lld" , &a[i]) ;            for(int j = i;j > 1;j--)            {                ll tmp = a[i] ;                for(int k = 0;k < 64;k++)                {                    ll tmp = ((ll)1<<k) ;                    if(tmp&a[i])                    {                        dp[j][k][0] += dp[j-1][k][1] ;                        dp[j][k][1] += dp[j-1][k][0] ;                    }                    else                    {                        dp[j][k][0] += dp[j-1][k][0] ;                        dp[j][k][1] += dp[j-1][k][1] ;                    }                    if(dp[j][k][0] >= mod)dp[j][k][0] -= mod ;                    if(dp[j][k][1] >= mod)dp[j][k][1] -= mod ;                }            }            for(int k = 0;k < 64;k++)            {                ll tmp = ((ll)1<<k) ;                if(tmp&a[i])                dp[1][k][1]++ ;                else dp[1][k][0]++ ;            }        }        ll ans = 0 ;        for(int i = 1;i <= n;i++)        {            ll ans = 0 ;            for(int j = 0;j < 64;j++)            {                ll tmp = (ll)1<<j ;                tmp = tmp%mod ;                tmp = (tmp*dp[i][j][1])%mod ;                ans = (ans + tmp)%mod ;            }            printf("%lld%c" , ans , i == n ?'\n':' ') ;        }    }    return 0 ;}

0 0