HDU5119 2014北京区域赛H DP

来源:互联网 发布:大卫芬奇电影知乎 编辑:程序博客网 时间:2024/06/05 15:21

给40个数,大小不超过100万,求异或和超过M的组合个数。

do[i][j]表示前i个数异或和是j的组合个数

然后就可以从i-1更新到i了,选第i个或者不选第i个,类似背包问题。

#include<iostream>#include<vector>#include<stdio.h>#include<math.h>#include<string.h>using namespace std;int A[50];int N,M;const int MAXN=1<<20;long long dp[42][MAXN+9];//前i(from 0)个异或和是j的组合的个数int big;long long solve(){    //for(int i=)    int cnt=0;    while(big>0){        big>>=1;        cnt++;    }    int maxres=1<<cnt;    memset(dp,0,sizeof(dp));    for(int i=0;i<N;i++){        for(int j=0;j<maxres;j++){            dp[i][j]=0;        }    }    dp[0][A[0]]=1;    dp[0][0]=1;    for(int i=1;i<N;i++){        for(int j=0;j<maxres;j++){            dp[i][j]+=dp[i-1][j];//不用第i个            //dp[i][j^A[i]]+=dp[i-1][j];            dp[i][j]+=dp[i-1][j^A[i]];            //cout<<"dp"<<i<<" "<<j<<" "<<dp[i][j]<<endl;        }    }    long long ans=0;    //cout<<maxres<<" ?"<<M<<endl;    for(int i=M;i<maxres;i++){        ans+=dp[N-1][i];        //cout<<"ans+"<<dp[N-1][i]<<endl;    }    return ans;}/*1002 1010 10*/int main(){    //cout<<(1<<20)<<endl;    int T;    cin>>T;    for(int i = 0 ; i < T ; i++){        cin>>N>>M;        big=0;        for(int j=0;j<N;j++){            scanf("%d",&A[j]);            big=max(big,A[j]);        }        cout<<"Case #"<<i+1<<": "<<solve()<<endl;    }    return 0;}