题意:
给你n个数字, 和m,让你求从这n个数字里面抽取若干个数字, 其异或和不小于m的方案数。
题解:
m的取值范围不超过 1000000
建一个二维的dp数组,通过滚动来进行dp
状态转移方程式为:dp[i%2][j] = dp[(i-1)%2][j] + dp[(i-1)%2][j^num[i]];
dp[(i-1)%2][j] 代表不取num[i]的的异或和为j的方案数
dp[(i-1)%2][j^num[i]] 代表取num[i]的的异或和为j的方案数 j^num[i]^num[i] = j
/*
Algorithm:
Author: anthony1314
Creat Time:
Time Complexity:
*/
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<set>
#include<stack>
#include<cstring>
#include<cstdio>
//#include<bits/stdc++.h>
#define ll long long
#define maxn 1005
#define mod 1e9 + 7
#define line printf("--------------\n");
using namespace std;
ll dp[2][2*1000005];
int num[45];
int main() {
int t;
cin>>t;
int cc = 1;
while(t--) {
int n, m;
cin>>n>>m;
for(int i = 1; i <= n; i++) {
scanf("%d", &num[i]);
}
memset(dp,0, sizeof(dp));
dp[0][0] = 1;
for(int i = 1; i <= n; i++) {
for(int j = 0; j < 1<<20; j++) {
dp[i%2][j] = dp[(i-1)%2][j] + dp[(i-1)%2][j^num[i]];
// cout<<dp[i%2][j]<<endl;
}
}
ll sum = 0;
for(int i = m; i < 1<<20; i++) {
sum+=dp[n % 2][i];
}
printf("Case #%d: ",cc++);
cout<<sum<<endl;
}
return 0;
}