[TCSRM518Div1]Nim
共K堆石子,数量均为<=L的质数,问初始必败状态的数量。
暴力dp就是f(i,x^y)+=f(i-1,x) y为质数
转换成分治f(i,x^y)=f(i/2,x)*f(i/2,y)(i为奇数乘个f(1))
暴力做是L^2
然后分治乘法可以搞。
一般分治乘法为(Ax+B)(Cx+D)=ACxx+BD+[(A+B)(C-D)-AC-BD]x T(N)=3*F(N/2)+O(N)
由于是xor,令x=2^k 则式子变为(Ax+B)(Cx+D)=(AD+BC)x+(AC+BD)=(P-Q)/2*x+(P+Q)/2 令P=(A+B)(C+D),Q=(A-B)*(C-D) T(N)=2F(N/2)+O(N)=O(NlogN)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
const int L=1<<16; const int mod=int(1e9)+7; const int inv2=500000004; bool pd[50010]; int n,D,F[L]; int res[L],ans[L]; int a[20][L],b[20][L],t0[20][L],t1[20][L]; void mul(int d) { if(d==0){a[0][0]=1LL*a[0][0]*b[0][0]%mod;return;} int i,w=1<<(d-1); rep(i,0,w-1)a[d-1][i]=(a[d][i]+a[d][i+w])%mod,b[d-1][i]=(b[d][i]+b[d][i+w])%mod; mul(d-1); CP(t0[d],a[d-1],w); rep(i,0,w-1)a[d-1][i]=(a[d][i]-a[d][i+w])%mod,b[d-1][i]=(b[d][i]-b[d][i+w])%mod; mul(d-1); CP(t1[d],a[d-1],w); rep(i,0,w-1)a[d][i]=1LL*(t0[d][i]+t1[d][i])*inv2%mod,a[d][i+w]=1LL*(t0[d][i]-t1[d][i])*inv2%mod; } void MUL(int*x,int*y) { CP(a[D],x,n); CP(b[D],y,n); mul(D); CP(x,a[D],n); } class Nim { public: int count(int K,int L) { int i,j; rep(i,2,L)if(!pd[i])rep(j,2,L/i)pd[i*j]=1; rep(i,2,L)if(!pd[i])F[i]=1; for(n=1,D=0;n<=L;n*=2,D++); ans[0]=1;for(;K;K>>=1,MUL(F,F))if(K&1)MUL(ans,F); return (ans[0]%mod+mod)%mod; } }TC;