hdu 5119 Happy Matt Friends

来源:互联网 发布:数据加密标准 编辑:程序博客网 时间:2024/05/18 03:45

        题意:n个数,可以取其中一部分来异或,问全部异或结果不小于m有多少种取法。

        思路:dp(背包)。dp(i,j)表示取到第i个数,异或结果为j,有多少种方法。初态是有一种取法取得0,然后对每个数,有两种选择,取或不取,加上上一步的路径数就可以了。最后将dp(n,j)中j>=m的部分求和就行。需要注意的是,会爆int。


#include<iostream>#include<cmath>#include<queue>#include<map>#include<set>#include<vector>#include<algorithm>#include<string.h>#include<cstdio>using namespace std;#define ll long longint a[50];bool vis[1050010];ll dp[2][1050010];vector<int> vec;int main(){        int t;    cin>>t;    int cas=0;    while(t--){        cas++;        memset(vis,0,sizeof(vis));        memset(dp,0,sizeof(dp));        vec.clear();                        int n,m;        cin>>n>>m;        for(int i=1;i<=n;i++){            scanf("%d",&a[i]);        }                vec.push_back(0);        vis[0]=1;        dp[0][0]=1;        for(int i=1;i<=n;i++){            int siz=vec.size();            int& cur=a[i];                        for(int j=0;j<siz;j++){                dp[i&1][vec[j]]=0;            }            for(int j=0;j<siz;j++){                dp[i&1][vec[j]^cur]+=dp[(i-1)&1][vec[j]];                dp[i&1][vec[j]]+=dp[(i-1)&1][vec[j]];                                if(vis[vec[j]^cur]==0){                    vis[vec[j]^cur]=1;                    vec.push_back(vec[j]^cur);                }            }        }        ll ans=0;        for(int i=m;i<1050010;i++){            ans+=dp[n&1][i];        }        printf("Case #%d: %I64d\n",cas,ans);    }    return 0;}


0 0
原创粉丝点击