/*Happy Matt Friends
Time Limit: 6000/6000 MS (Java/Others) Memory Limit: 510000/510000 K (Java/Others)
Total Submission(s): 970 Accepted Submission(s): 390
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
2
3 2
1 2 3
3 3
1 2 3
Sample Output
Case #1: 4
Case #2: 2
HintIn the ?rst 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
2014ACM/ICPC亚洲区北京站-重现赛(感谢北师和上交)
Recommend
liuyiding | We have carefully selected several similar problems for you: 5338 5337 5336 5335 5334
*/
#include<stdio.h>
#include<string.h>
int n, m, a[44];
__int64 dp[2][1050010];//10的六次方进行异或运算不会超过2^20
int main()
{
int t, cas = 1;
scanf("%d", &t);
while(t--)
{
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i)
scanf("%d", &a[i]);
memset(dp, 0, sizeof(dp));
dp[0][0] = 1;
for(int i = 1; i <= n; ++i)
{
for(int j = 0; j < 1048576; ++j)
dp[1][j] = dp[0][j];
for(int j = 0; j < 1048576; ++j)
{
int k = j^a[i];
dp[1][k] += dp[0][j];
}
for(int j = 0; j < 1048576; ++j)
dp[0][j] = dp[1][j];
}
__int64 k = 0;
for(int i = m; i < 1048576; ++i)
k += dp[1][i];
printf("Case #%d: %I64d\n", cas++, k);
}
return 0;
}
题意:给出n和m,然后再给出n个数,求其中有多少种组合能够使他们的异或和大于等于m。
思路:用DP的思想dp【i】【j】表示对于前i个数他们的异或和为j的方案数,那么dp【i+1】【j】就相当于是前一个的dp【i】【j】+dp【i】【某个j^第i+1个数】的方案数。
难点:这里有个很坑的细节问题就是输入的数保证在10^6之内,但是异或以后却有可能大于10^6,所以数组一定要比2^20大,否则就会发生访问非法内存了,其次就是最后的答案相加,题目要求的是比m大的数的方案全部要加起来,却没说上限,上限其实就是2^20,所以这个题最大的难点就在于这个上限了,要是没考虑到这一点,很难做对这一题。