hdoj Happy Matt Friends 5119 (DP) 好题

来源:互联网 发布:c语言经典编程282例txt 编辑:程序博客网 时间:2024/05/16 10:34

Happy Matt Friends

Time Limit: 6000/6000 MS (Java/Others)    Memory Limit: 510000/510000 K (Java/Others)
Total Submission(s): 1828    Accepted Submission(s): 725


Problem Description
Matt has N friends. They are playing a game together.

Each of Matt’s friends has a magic number. In the game, Matt selects some (could be zero) of his friends. If the xor (exclusive-or) sum of the selected friends’magic numbers is no less than M , Matt wins.

Matt wants to know the number of ways to win.

Input
The first line contains only one integer T , which indicates the number of test cases.

For each test case, the first line contains two integers N, M (1 ≤ N ≤ 40, 0 ≤ M ≤ 106).

In the second line, there are N integers ki (0 ≤ ki ≤ 106), indicating the i-th friend’s magic number.

Output
For each test case, output a single line “Case #x: y”, where x is the case number (starting from 1) and y indicates the number of ways where Matt can win.

Sample Input
23 21 2 33 31 2 3

Sample Output
Case #1: 4Case #2: 2
Hint
In the first sample, Matt can win by selecting:friend with number 1 and friend with number 2. The xor sum is 3.friend with number 1 and friend with number 3. The xor sum is 2.friend with number 2. The xor sum is 2.friend with number 3. The xor sum is 3. Hence, the answer is 4.

题意:给n个数,再给一个m,问有多少种方案,从这n个数中选出若干个(可以是0个),他们的异或值大于等于m。

d[i][j]表示前i个人异或状态为j的方案数。

则 d[i][j] = d[i-1][j] + d[i-1][j^a[i]] 分别表示第i个数不取和第i个数取情况下状态

//一开始这样写1608Ms
#include<stdio.h>#include<string.h>#include<math.h>#define N 1<<20+1int dp[41][N];int a[50];int main(){int t;int T=1;int n,m;scanf("%d",&t);while(t--){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%d",&a[i]);dp[0][0]=1;for(int i=1;i<=n;i++){for(int j=0;j<=N;j++){dp[i][j]=dp[i-1][j]+dp[i-1][j^a[i]];}}long long cnt=0;for(int j=m;j<N;j++)cnt+=dp[n][j];printf("Case #%d: %lld\n",T++,cnt); }return 0;}

//队友用滚动数组写785Ms,我也试了下但还是1700Ms。。。。。(代码基本一样)
#include<stdio.h>#include<string.h>#include<algorithm>#define N 1<<20+1using namespace std;int a[50];int dp[2][N];int main(){int t;int T=1;int n,m,i,j;scanf("%d",&t);while(t--){scanf("%d%d",&n,&m);memset(dp,0,sizeof(dp));dp[0][0]=1;for(i=1;i<=n;i++)scanf("%d",&a[i]);int x=0;for(i=1;i<=n;i++){x^=1;for(j=0;j<N;j++){dp[x][j]=dp[x^1][j]+dp[x^1][j^a[i]];}}long long cnt=0;for(i=m;i<N;i++)cnt+=dp[x][i];printf("Case #%d: %lld\n",T++,cnt);}return 0;}

下面的是队友的785Ms。
#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>using namespace std;const int INF=0x3f3f3f3f;const int MAXN=1<<20;int dp[2][MAXN<<1];//刚开始开到MAXN+10 RE,改成这才对; int main(){    int T,N,M,flot=0;    int m[41];    scanf("%d",&T);    while(T--){        scanf("%d%d",&N,&M);        memset(dp,0,sizeof(dp));        dp[0][0]=1;        int x=0;        for(int i=0;i<N;i++){            x^=1;            scanf("%d",m+i);            for(int j=0;j<=MAXN;j++){                dp[x][j]=dp[x^1][j]+dp[x^1][j^m[i]];                //代表上一次值为j^m[i]现在再^m[i]等于j了再加上上次j的个数;             }        }        long long ans=0;        for(int i=M;i<=MAXN;i++)ans+=dp[x][i];        printf("Case #%d: %lld\n",++flot,ans);    }    return 0;}

0 0
原创粉丝点击