题意:给出n个数,每个数字代表0到这个数字的范围,每个里面要选一个,求异或和为K的情况总数。
做法:挺难想的一个dp,我们把这些数换成2进制组成一个表格,首先可以明确一点,只要有一位可以随便放的二进制数的位(因为前面有的位已经使得比原数小了)不随便放,那么其他数这个位的0或1随便放,都可以达到想要的答案。而每一个位只需要一个这样的位就可以达到效果了,所以我们就规定第一个能随便放的地方不随便放,这样后来这个位就真的可以随便放了。
所以可以用dp[i][j]代表到前i个数,前0-j-1的位数的组合可以得到任意一个数的情况总数。那么枚举下一个数二进制1的位置(把这个1变成0后面的就随便放了)的时候就要把位置跟j比较,如果比j小,那么从这个位置到j的位置是这几个位数第一个出现随便放的位置,那么我们就不让他随便放,在j到0之间的则可以随便放(因为前面已经有不随便放的位置故可以得到任何想得到的答案)。反之,就那个位置到0可以随便放。
最后算答案的时候,0到j-1是可以得到想得到的数的,j+1到最大位是跟原数是一样的。一个一个异或跟K比较下,如果不等说明不满足。但是关键是j那个位置不知道到底是1还是0,而且这一位也不是想得到什么就能得到什么的。所以我们把dp再加上一维,dp[i][j][k]代表前i个数,前0到j-1的位数组合可以得到任意一个数,而且第j位组合可以得到k(0或者1)的情况总数。这样我们根据K的那一位为几就把答案加上谁就可以了。
#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<ctype.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdlib>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<cmath>
#include<ctime>
#include<string.h>
#include<string>
#include<sstream>
#include<bitset>
using namespace std;
#define ll __int64
#define ull unsigned __int64
#define eps 1e-8
#define NMAX 1000000000
#define MOD 1000000003
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define PI acos(-1)
template<class T>
inline void scan_d(T &ret)
{
char c;
int flag = 0;
ret=0;
while(((c=getchar())<'0'||c>'9')&&c!='-');
if(c == '-')
{
flag = 1;
c = getchar();
}
while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar();
if(flag) ret = -ret;
}
const int maxn = 55;
ll g[55][55][2],a[55];
int xo[55][55];
int main()
{
#ifdef GLQ
freopen("input.txt","r",stdin);
// freopen("o1.txt","w",stdout);
#endif
int n;
ll K;
ll one = 1;
while(~scanf("%d%I64d",&n,&K) && n+K)
{
for(int i = 1; i <= n; i++)
scanf("%I64d",&a[i]),a[i]++;
memset(g,0,sizeof(g));
for(int i = 0; i <= 31; i++) if(a[1]&(one<<i))
g[1][i][0] = 1;
for(int i = 0; i <= 31; i++)
for(int j = 1; j <= n; j++)
if(j == 1) xo[i][j] = (a[j]&(one<<i)) == 0 ? 0 : 1;
else xo[i][j] = xo[i][j-1]^((a[j]&(one<<i)) == 0 ? 0 : 1);
for(int i = 1; i < n; i++)
for(int j = 0; j <= 31; j++) if(g[i][j][0] || g[i][j][1])
for(int k = 0; k <= 31; k++) if(a[i+1]&(one<<k))
{
if(k <= j)
{
if(k == j || (a[i+1]&(1<<j)) == 0)
{
g[i+1][j][0] += g[i][j][0]*(one<<k)%MOD;
g[i+1][j][1] += g[i][j][1]*(one<<k)%MOD;
}
else
{
g[i+1][j][0] += g[i][j][1]*(one<<k)%MOD;
g[i+1][j][1] += g[i][j][0]*(one<<k)%MOD;
}
g[i+1][j][0] %= MOD;
g[i+1][j][1] %= MOD;
}
else
{
g[i+1][k][xo[k][i]] += (g[i][j][0]+g[i][j][1])%MOD*(one<<j)%MOD;
g[i+1][k][xo[k][i]] %= MOD;
}
}
ll ans = 0;
// cout<<g[n][0][0]<<endl;
for(int i = 31; i >= 0; i--)
{
int tmp = (K&(one<<i)) == 0 ? 0 : 1,ha = 0;
// cout<<i<<" "<<tmp<<" "<<g[n][i][tmp]<<endl;
ans += g[n][i][tmp];
ans %= MOD;
for(int j = 1; j <= n; j++)
ha ^= ((a[j]&(one<<i)) == 0 ? 0 : 1);
if(ha != tmp) break;
}
printf("%I64d\n",ans);
}
return 0;
}