博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
2014年北京 happy matt friends(dp + 滚动数组优化)
阅读量:4477 次
发布时间:2019-06-08

本文共 3183 字,大约阅读时间需要 10 分钟。

Happy Matt Friends

Time Limit: 6000/6000 MS (Java/Others)    Memory Limit: 510000/510000 K (Java/Others)

Total Submission(s): 6164    Accepted Submission(s): 2330

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 ≤ 10
6).
In the second line, there are N integers ki (0 ≤ k
i ≤ 10
6), 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
2 3 2 1 2 3 3 3 1 2 3
 

 

Sample Output
Case #1: 4 Case #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.
 

 

Source
 

 

Recommend
liuyiding
 
这题比赛时候居然没有做出来呜呜呜,我对dp的学习路线让人怀疑。。。。
 
接下来分析一下这个题
 
本题大意:给定n个数,让你在n个数字中选择任意多个数字,使得他们的异或和 >= m。
你不知道某些数字选还是不选,多选或者少选都可能多一种方案,看数据范围数字总共不到40个,
最大值在1e6以内,所以这些值异或之后的最大值也不超过1 << 20,所以应该就要想到一个数字
选还是不选应该是最重要的,他选了之后对于已经选过的值的影响的记录也是必要的,所以肯定要
知道某个值选不选?然后还要把异或之后的值记录下来,记录的话肯定是需要一维记录了,我们想到可以把这些数可以异或得到的所有结果记录下来,然后查询大于等于m的个数有多少个即可。所以索性我们就假设dp[ i ][ j ]为前i个数,选择一些异或起来异或和为 j 的方案数,这样我们很容易就可以得到递推方程dp[ i ][ j ] = dp[i - 1][j ^ a[ i ]] + dp[i - 1][ j ],那就是一个数选或者不选,有两种情况,方法数相加。
 
哦,一看就知道要开4 * 1e7的long long的数组,写出方程后应该可以想到数组是可以滚动的,因为
对于每前i个的计算只需要前i - 1 个数的状态,所以我们索性就开一个dp[ 2 ][ maxn ]的数组,用 & 来滚动数组就行了。哦,具体见代码。
 
1 /* 2     本题思路:用dp[i][j]表示前i个数可以凑出数字j的方法数目。 3     dp[i][j] = dp[i - 1][j ^ a[i]] + dp[i - 1][j]; 4 */ 5 #include 
6 #include
7 #include
8 using namespace std; 9 10 const int maxn = 40 + 5, maxm = 1 << 20;11 int n, m;12 13 typedef long long ll;14 15 int a[maxn];16 17 ll dp[2][maxm];18 19 int main() {20 int t, _case = 0;21 scanf("%d", &t);22 while(t --) {23 memset(dp, 0, sizeof dp);24 scanf("%d %d", &n, &m);25 for(int i = 1; i <= n; i ++) {26 scanf("%d", &a[i]);27 }28 /*29 dp[0][0] = 1;30 for(int i = 1; i <= n; i ++) {31 for(int j = 0; j < maxm; j ++) {32 dp[i][j] = dp[i - 1][j ^ a[i]] + dp[i - 1][j];33 }34 }35 */36 dp[0][0] = 1;37 for(int i = 1; i <= n; i ++) {38 for(int j = 0; j < maxm; j ++) {39 dp[i & 1][j] = dp[i - 1 & 1][j ^ a[i]] + dp[i - 1 & 1][j]; 40 }41 }42 ll ans = 0;43 for(int i = m; i < maxm; i ++) {44 ans += dp[n & 1][i];45 }46 printf("Case #%d: %lld\n", ++ _case, ans);47 }48 return 0;49 }

 

转载于:https://www.cnblogs.com/bianjunting/p/11599201.html

你可能感兴趣的文章
Best Quality CAT Caterpillar ET Diagnostic Adapter III
查看>>
定向转发和重定向实现 <select >下拉表单数据传送
查看>>
数组与字符串一(概念和基础)
查看>>
用cocos2d-html5做的消除类游戏《英雄爱消除》(4)——游戏结束
查看>>
CNUOJ 535 黑魔法师之门
查看>>
18. Maven 的单模块 / 多模块之 Spring MVC + Spring + Mybatis 项目讲解(重点)
查看>>
vs2017 F5不会自动编译了
查看>>
hdu 1028
查看>>
取消 Win7 驱动数字签名认证 WIN7 X64 系统
查看>>
East Brother Video Indoor Monitor
查看>>
Python基础数据类型2
查看>>
linux Shell脚本编码格式
查看>>
【转】人脸表情识别综述
查看>>
【转】OpenCV图像处理 图像的点运算 ( 灰度直方图 )
查看>>
斜率优化DP学习笔记
查看>>
vim 操作命令大全(转)
查看>>
<C++>CLR必须定义入口点
查看>>
TFS自动记住用户名密码 免密码自动登录
查看>>
Leetcode-290 Word Pattern(单词模式)
查看>>
搜索输入框提示--输入延迟,仿自动脑学院
查看>>