hdoj Happy Matt Friends 5119 (DP) 好题
2015-10-23 20:47
399 查看
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
[align=left]Problem Description[/align]
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.
[align=left]Input[/align]
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.
[align=left]Output[/align]
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.
[align=left]Sample Input[/align]
2
3 2
1 2 3
3 3
1 2 3
[align=left]Sample Output[/align]
Case #1: 4
Case #2: 2
HintIn 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+1 int dp[41] ; 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 [j]; printf("Case #%d: %lld\n",T++,cnt); } return 0; }
//队友用滚动数组写785Ms,我也试了下但还是1700Ms。。。。。(代码基本一样)
#include<stdio.h> #include<string.h> #include<algorithm> #define N 1<<20+1 using namespace std; int a[50]; int dp[2] ; 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; }
相关文章推荐
- Object of class stdClass could not be converted to string
- iOS经典讲解之Swift匿名函数(闭包)(二)
- ios学习之cocoa的大致了解
- Android基础和运行机制
- Android 常用colors xml
- Android Material Design之Toolbar与Palette实践
- iOS-响应上下左右滑动手势
- 输出无名空数组---精android、IOS App应用服务程序开发
- iOS开发中使用宏定义提高开发效率
- Windows Server AppFabric与WCF
- Windows Server AppFabric与WCF
- iOS宏定义的使用与规范
- Android Lint清除无用的资源文件
- Swift基础知识
- [Android基础]动画xml文件
- Android aapt 命令 详细解析
- Android
- 数据源和连接池DataSource Objects and Connection Pools
- 简单异或加密代码--IOS版(广点通)
- android RecyclerView响应点击事件(二)