MTT
任意模数FFT时记M为sqrt(mo)
将每个数a分为a/M,a%M后分别进行三次实数FFT
const LL mo=1e9+7; const LL M=sqrt(mo); const LDB pi=acos(-1); LL cunt[511][511]; struct cp{ LDB r,i; }a1[511][1024],a2[511][1024],tmp[1024]; inline cp operator +(cp a,cp b) {return((cp){a.r+b.r,a.i+b.i});}; inline cp operator -(cp a,cp b) {return((cp){a.r-b.r,a.i-b.i});}; inline cp operator *(cp a,cp b) {return((cp){a.r*b.r-a.i*b.i,a.i*b.r+a.r*b.i});}; void FFT(cp a[],int n,int fl){ for (int i=1,j=n/2;i<n;i++){ if (i<j) {cp t=a[i];a[i]=a[j];a[j]=t;}; int k; for (k=(n>>1);j&k;j^=k,k>>=1); j^=k; } for (int i=2;i<=n;i<<=1){ cp w;w.r=cos(fl*2*pi/i);w.i=sin(fl*2*pi/i); for (int j=0;j<n;j+=i){ cp wi;wi.r=1;wi.i=0; for (int k=j;k<j+i/2;k++){ cp u=a[k],v=a[k+i/2]*wi; a[k]=u+v;a[k+i/2]=u-v; wi=wi*w; } } } if (fl==-1) for (int i=0;i<n;i++) a[i].r/=n,a[i].r=((LL)(a[i].r+0.5)%mo); } class BagAndCards { public: int getHash(LL n, LL m, LL x, LL a, LL b, LL c, string isGood) { for (int i=0;i<n;i++) for (int j=0;j<m;j++) cunt[i][j]=x,x=((x*a+b)^c)%mo; for (int i=0;i<n;i++){ for (int j=0;j<m;j++) a1[i][j]=(cp){cunt[i][j]%M,0}, a2[i][j]=(cp){cunt[i][j]/M,0}; FFT(a1[i],1024,1); FFT(a2[i],1024,1); } LL ret=0; for (int i=0;i<n;i++) for (int j=i+1;j<n;j++){ LL ans=0; for (int k=0;k<1024;k++) tmp[k]=a2[i][k]*a2[j][k]; FFT(tmp,1024,-1); for (int k=0;k<2*m-1;k++) if (isGood[k]=='Y') ans+=((LL)tmp[k].r)%mo*M%mo*M%mo,ans%=mo; for (int k=0;k<1024;k++) tmp[k]=a1[i][k]*a2[j][k]+a2[i][k]*a1[j][k]; FFT(tmp,1024,-1); for (int k=0;k<2*m-1;k++) if (isGood[k]=='Y') ans+=((LL)tmp[k].r)%mo*M%mo,ans%=mo; for (int k=0;k<1024;k++) tmp[k]=a1[i][k]*a1[j][k]; FFT(tmp,1024,-1); for (int k=0;k<2*m-1;k++) if (isGood[k]=='Y') ans+=((LL)tmp[k].r)%mo,ans%=mo; ret^=ans; } return(ret); }