题解 P5970 【[POI2016]Nim z utrudnieniem】
发现自己两年前做的题目洛谷上有了,开心。其实题解也是那个时候写的。
Nim游戏中,当
由此我们要在原来的局面中让后手取
这样我们就可以转移一个
这个时候则有:
这样做的话,时间复杂度为
有一个很巧妙的想法是:因为对于任意一个正整数
最后有个小细节要注意一下:当
然后后来就在bzoj上rank1了。(现在rank3)
/**************************************************************
Problem: 4347
User: rourou
Language: C++
Result: Accepted
Time:9516 ms
Memory:52464 kb
****************************************************************/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cctype>
using namespace std;
int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
const int MOD=1e9+7;
int n,d,a[500050],f[11][1050000],g[1050000];
int main()
{
n=read(),d=read();
int s=0;
for (int i=1;i<=n;i++)
s^=(a[i]=read());
sort(a+1,a+n+1);
f[0][0]=1;
int u=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 k=0;k<u;k++)
f[j][k]=(f[j][k]+f[j-1][k^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;
cout << f[0][s] << endl;
return 0;
}