mod下答案为负数时没加上mod…
去完石子就是个nim游戏,所有石子异或和为0则先手必败
设所有石子异或和为s
就是问取kd堆石子,有多少种情况使得取了的石子异或和为s
令f[i][j][k]表示处理完前i堆石子,取了的堆数在mod d下为j,取了的石子异或和为k的方案数
直接转移O(ndmaxa)
但可以发现a[i]和小于a[i]的数异或和不会超过2*a[i]
所以我们将石子排序后,复杂度就可以降到O(dm)了
然后这题还卡空间,不能用滚动..
观察转移f[i][j][k]=f[i-1][j-1][k^a[i]]+f[i-1][j][k]
我们发现可以不滚动..
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
#define inf 1e9
using namespace std;
const int maxd = 10;
const int maxm = 1050000;
const int Mod = 1e9+7;
int n,m,d;
int a[maxm];
int f[maxd][maxm],g[maxm];
int main()
{
scanf("%d%d",&n,&d);
int s=0;
for(int i=1;i<=n;i++) scanf("%d",&a[i]),s^=a[i];
sort(a+1,a+n+1);
int u=1;
f[0][0]=1;
for(int i=1;i<=n;i++)
{
while(u<=a[i]) u<<=1;
for(int j=0;j<u;j++) g[j]=(f[d-1][j^a[i]]+f[0][j])%Mod;
for(int j=d-1;j>0;j--) for(int l=0;l<u;l++)
f[j][l]=(f[j][l]+f[j-1][l^a[i]])%Mod;
for(int j=0;j<u;j++) f[0][j]=g[j];
}
if(n%d==0) f[0][s]--;
if(f[0][s]<0) f[0][s]+=Mod;
printf("%d\n",f[0][s]);
return 0;
}