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.
题意:
在大小为n的集合中,找出子集异或结果大于等于M的子集个数。
前 i 个数异或后的结果为 j 的方案数 = 前 i - 1 个数异或后的结果为 j 的方案数 +前 i -1个数异或结果为 j ^a[i] 的方案数。
状态转移方程式 dp[i[j]=dp[i-1][j]+dp[i-1][j^a[i]];
注意:n的数据范围是40,看着可能不会超时,可以直接暴力,在实际上是遍历的时候子集有2^40,这样的话就会超时,一开始本来是不理解为啥要用dp 来写,看看数据,就突然明白了;
代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define ll long long
#define maxx 1024*1024
int a[45];
ll dp[45][maxx];///dp[i][j]代表从第1个数到第i个数,亦或后结果为j的方案的数目
///任何数和0异或后的·结果依然是本身
int main()
{
int t,n,m,c=1;
scanf("%d",&t);
while(t--)
{
memset(dp,0,sizeof(dp));
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<maxx; j++)
dp[i][j]=dp[i-1][j]+dp[i-1][j^a[i]];
ll sum=0;
for(int k=m; k<maxx; k++)
sum+=dp[n][k];
printf("Case #%d: %lld\n",c++,sum);
}
}