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 ≤ ).
In the second line, there are N integers ki (0 ≤ ki ≤ ), 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.
题目大意
有n个数,取出几个数的算出他们的异或的和,求大于等于m的异或和有多少种情况。
用dp[i][j]表示用前n个数,他们之间组合的异或结果为j的情况个数。dp[i][j] = dp[i-1][j^a[i]] + dp[i-1][j] ,新添加一个数,异或为j的情况分为两种:不要这个数的情况dp[i-1][j],要这个数的情况dp[i-1][j^a[i]],两种情况合起来就是dp[i][j]。
dp[0][0]=1,这个初始化可以理解为0个数异或为0的情况的个数为1(感觉不太对)。其实按常理说应该把n个数初始化为1,dp[1][a[i]] = 1,很多dp求情况和的问题的初始化都是一个简单的dp[0][0] = 1,因为在i=1的时候,做的就是dp[1][a[i]] = 1。本质是一样的,而且写法更加简约。
关于 Max = 1<<20,数最大是,可以看做是1024即,那么最大就应该是,用位运算符表示就是1<<20,这些数的异或和最大最大无非是全写1。
关于使用long long存sum,考虑最坏的情况,m=0,那么所有的情况都符合,所有组合加起来就是,n最大为40,int最大就是20亿,显然已经超过了。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int Max = 1<<20;
int dp[45][Max],a[45];
int n,m;
void init()
{
memset(dp,0,sizeof(dp));
dp[0][0] = 1;
for(int i=1;i<=n;i++){
for(int j=0;j<Max;j++){
dp[i][j] = dp[i-1][j^a[i]] + dp[i-1][j];
}
}
}
int main()
{
int T;scanf("%d",&T);
for(int k=1;k<=T;k++)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
init();
ll sum=0;
for(int i=m;i<Max;i++)
sum += dp[n][i];
printf("Case #%d: %lld\n",k,sum);
}
return 0;
}