bzoj4589 Hard Nim
分析
我们已知所有堆的异或和为0是后手必胜
我们又知道只有一堆时只有异或和为质数的情况为1其它为0
又因为ans[k][i^j] = ans[k-1][i] * ans[k-1][j]
所以直接fwt即可
我们可以对a数组fwt后用快速幂取它的n次方,然后再ifwt回来即可
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
const int mod = 1e9+7;
int n,m,N,a[200100],p[50010],cnt,inv;
bool is[50010];
inline int pw(int x,int p){
int res=1;
while(p){
if(p&1)res=1ll*res*x%mod;
x=1ll*x*x%mod;
p>>=1;
}
return res;
}
inline void prework(){
inv=pw(2,mod-2);
for(int i=2;i<50000;i++)
if(!is[i]){
p[++cnt]=i;
for(int j=i;j<=50000;j+=i)is[j]=1;
}
}
inline void init(){
memset(a,0,sizeof(a));
n=1;
while(n<=m)n<<=1;
for(int i=1;i<=cnt&&p[i]<=m;i++)a[p[i]]=1;
}
inline void fwt(int a[],int f){
int i,j,k;
for(i=1;i<n;i<<=1)
for(j=0;j<n;j+=(i<<1))
for(k=0;k<i;k++){
int x=a[j+k],y=a[i+j+k];
a[j+k]=(x+y)%mod,a[i+j+k]=(x+mod-y)%mod;
if(f==-1)a[j+k]=1ll*a[j+k]*inv%mod,a[i+j+k]=1ll*a[i+j+k]*inv%mod;
}
}
int main(){
int i,j,k;
prework();
while(scanf("%d%d",&N,&m)!=EOF){
init();
fwt(a,1);
for(i=0;i<n;i++)a[i]=pw(a[i],N);
fwt(a,-1);
printf("%d\n",a[0]);
}
return 0;
}