题目:点击打开链接
题意:给你n个数和一个数m,在这n个数中选任意个数求异或和,要求所得值大于等于m的种数。
解法:dp[i][j]表示达到i状态异或结果为j的种数,状态转移方程:dp[i][j]=dp[i-1][j]+dp[i-1][j^a[i]];
即取到第i个数时异或等于j的种数 等于取到第i-1个数时异或等于j的种数 + 取到第i-1个数时异或等于j^a[i]的种数;
j^a[i]为:一个数和a[i]异或等于j,那么j和a[i]异或就等于那个数(位运算的神奇);
然后这个题可能会超空间需要用滚动数组。
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
#include <iostream>
#include <cstring>
using namespace std;
long long dp[2][1<<20];
int main()
{
int t,k,n,m,a[45];
long long ans;
cin>>t;
k=0;
while(t--)
{
k++;
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[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^a[i]];
ans=0;
for(int i=m;(i<1<<20);i++)
ans+=dp[n%2][i];
cout<<"Case #"<<k<<": "<<ans<<endl;
}
return 0;
}