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);
    }