题意:给定n个数,有多少种方案使从中取k个数(0<=k<=n)的异或和结果大于等于m
因为可以从前i个数的状态推出前i+1个数的状态,故考虑dp,而dp数组记录的应该为对应的方案数。
用dp[i][j]表示前i个数xor sum为j的方案数,初始化dp[0][0]为1,最后的答案就是
dp[i-1][j]分两个转移方向:
1. 取第i个数:dp[i+1][j^a[i]]
2.不取第i个数:dp[i+1][j]
#include <iostream>
#include <cstring>
#define INF 0x3f3f3f3f
#define PB emplace_back
#define MP make_pair
#define fi first
#define se second
#define rep(i,a,b) for(repType i=(a); i<=(b); ++i)
#define per(i,a,b) for(repType i=(a); i>=(b); --i)
#define ZERO(x) memset(x, 0, sizeof(x))
#define MS(x,y) memset(x, y, sizeof(x))
#define ALL(x) (x).begin(), (x).end()
#define QUICKIO \
ios::sync_with_stdio(false); \
cin.tie(0); \
cout.tie(0);
#define DEBUG(...) fprintf(stderr, __VA_ARGS__), fflush(stderr)
using namespace std;
using pi=pair<int,int>;
using repType=int;
using ll=long long;
using ld=long double;
using ull=unsigned long long;
const int maxn=1<<20;
ll dp[45][maxn];
int main()
{
QUICKIO
//cout<<(1<<20)<<endl;
int a[45];
int m,n;
int t;
cin>>t;
rep(kase,1,t)
{
memset(dp,0,sizeof(dp));
dp[0][0]=1;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for(int i=1;i<=n;i++)
{
for(int j=maxn;j>=0;j--)
{
dp[i][j^a[i]]+=dp[i-1][j];
dp[i][j]+=dp[i-1][j];
}
}
/*
rep(i,0,3)
{
rep(j,0,16)
{
printf("(%d,%d)=%lld ",
i,j,dp[i][j]);
}
cout<<endl;
}
*/
ll ans=0;
for(int j=m;j<=maxn;j++)
{
ans+=dp[n][j];
}
cout<<"Case #"<<kase<<": "<<ans<<endl;
}
return 0;
}