BZOJ3992: [SDOI2015]序列统计

https://www.lydsy.com/JudgeOnline/problem.php?id=3992

有a*bΞx(mod m),则ord(a)+ord(b)Ξord(x)(mod φ(m))

对Σxord(si)循环卷积FFT即可

#include<cstdio>
#include<algorithm>
#define re register 
#define rep(i,s,t) for(re int i=s;i<=t;++i)
#define Rep(i,s,t) for(re int i=s;i<t;++i)
using namespace std;
const int N=4e5+11,mod=1004535809;
int n,m,x,s,g,sum,d,lg2;
int q[N],ord[N],a[N],p[N],res[N];
inline void inc(int &a,int b){
    a+=b;
    if(a>=mod)a-=mod;
    if(a<0)a+=mod;
}
inline int fp(int a,int b,int m=mod){
    if(b<0)b+=m-1;
    if(b>=m-1)b-=m-1;
    int res=1;
    for(;b;b>>=1,a=1ll*a*a%m)
        if(b&1)
            res=1ll*res*a%m;
    return res;
}
inline int findg(int x){
    int t=0;
    for(re int i=2;i*i<=x-1;++i)
        if((x-1)%i==0){
            q[++t]=i;
            if(i*i!=x-1)
                q[++t]=(x-1)/i;
        }
    rep(i,2,(1<<30)){
        rep(j,1,t)
            if(fp(i,q[j],x)==1)
                goto end;
        return i;
        end:;
    }
}
inline void dft(int *a,int n,int f){
    Rep(i,0,n)
        if(i<p[i])
            swap(a[i],a[p[i]]);
    for(re int i=1,x,y;i<n;i<<=1){
        for(re int w,j=0,wn=fp(3,(mod-1)/(i<<1)*f);w=1,j<n;j+=(i<<1)){
            for(re int k=j;k<i+j;++k,w=1ll*w*wn%mod){
                x=a[k],y=1ll*w*a[i+k]%mod;
                a[k]=(x+y)%mod;
                a[i+k]=(x-y+mod)%mod;
            }
        }
    }
    if(f==-1){
        int inv=fp(n,mod-2);
        Rep(i,0,d)
            a[i]=1ll*a[i]*inv%mod;
    }
}
int main(){
    //freopen("test.in","r",stdin);
    scanf("%d%d%d%d",&n,&m,&x,&s);
    g=findg(m),sum=1;
    //printf("%d\n",g);
    rep(j,0,m-1){
        ord[sum]=j;
        sum=1ll*sum*g%m;
    }
    for(int x;s--;){
        scanf("%d",&x);
        if(x)++a[ord[x]];
    }
    for(d=1,lg2=-1;d<=m+m;d<<=1,++lg2);
    Rep(i,0,d)p[i]=(p[i>>1]>>1)^((i&1)<<lg2);
    Rep(i,0,d)res[i]=a[i];
    for(--n;n;n>>=1){
        dft(a,d,1);
        if(n&1){
            dft(res,d,1);
            Rep(i,0,d)res[i]=1ll*res[i]*a[i]%mod;
            dft(res,d,-1);
            Rep(i,0,m-1)inc(res[i],res[i+m-1]);
            Rep(i,m-1,d)res[i]=0;
        }
        Rep(i,0,d)a[i]=1ll*a[i]*a[i]%mod;
        dft(a,d,-1);
        Rep(i,0,m-1)inc(a[i],a[i+m-1]);
        Rep(i,m-1,d)a[i]=0;
    }
    printf("%d\n",res[ord[x]]);
    return 0;
}
code

 

posted @ 2018-06-18 16:40  Stump  阅读(177)  评论(0编辑  收藏  举报