[BZOJ3992] [SDOI2015] sequence statistics

[BZOJ3992] [SDOI2015] sequence statistics”

Description

Small C has a set of S whose elements are all non negative integers less than M. He programmed a sequence generator to generate a N-length sequence in which each number belongs to the set S. Small C uses this generator to generate many such sequences. But little C has a problem that needs you.Help: Given the integer x, find how many different sequences of numbers can be generated that satisfy the value of the product mod M of all the numbers in the sequence equal to X. Small C holds that two sequences {Ai} and {Bi} are different if and only if there is at least one integer I satisfying Ai_Bi. In addition, smallC thinks the answer to this question may be big, so he just needs you to help him figure out the value of mod 1004535809.

Input

A row, four integers, N, M, x, |S|, where |S| is the number of elements in the set S. The second line, |S| integers, represents all the elements in the set S. 1< =N< =10^9; 3< =M< =8000, M are prime numbers 0< =X< =M-1, input data ensure that the elements in the collection S are not duplicated, X [1, m-1]
The number of [0 in the collection, m-1]

Output

One line, one integer, indicates the value of the number of mod 1004535809 that you get.

Sample Input

4 3 1 2
1 2

Sample Output

8
【Sample Note: The different sequences that can be generated to meet the requirements are (1,1,1,1,2,2), (1,2,1,2), (1,2,2,1), (2,1,1,2), (2,1,2,1), (2,2,1), (2,2,1), (2,2,1,(2,2,2)

\(p\)by\(mod\)The original roots, then\(p^0\to p^{mod-2} \pmod{mod}\)You can represent all the numbers of 1~mod-1.
In this way, we can get indicators for each number.\(p^x=y\),among\(x\)by\(y\)Then we can turn multiplication into exponential addition, and NTT polynomials can be fast.

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
 
using namespace std;
#define LL long long
#define G 3
#define Mod 1004535809LL
 
inline LL read(){
    LL x=0,f=1; char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    return x*f;
}
const LL MAXN = 100010;
const LL INF = 2147473600;
 
LL N,M,X,S; LL top,rev[MAXN+1];
LL s[MAXN+1],sta[MAXN+1];
LL a[MAXN+1];
 
inline LL Pow(LL A,LL B,LL P){
    LL res=1;
    while(B){
        if(B&1) res=res*A%P;
        A=A*A%P; B>>=1;
    } return res;
} 
inline LL GetN(LL x){
    LL y=x-1;
    for(LL i=2;y!=1;i++) {
        if(y%i==0) sta[++top]=i;
        while(y%i==0) y/=i;
    }
    for(LL i=2;;i++){
        bool flag=1;
        for(LL j=1;j<=top;j++)
            if(Pow(i,(x-1)/sta[j],x)==1) {flag=false; break;}
        if(flag) return i;
    }
}
LL a1[MAXN+1],b1[MAXN+1],c1[MAXN+1],b[MAXN+1],t[MAXN+1];
inline void NTT(LL *A,LL lim,LL type){
    for(LL i=0;i<lim;i++) if(rev[i]>i) swap(A[rev[i]],A[i]);
    for(LL mid=1;mid<lim;mid<<=1){
        LL Wn = Pow(G , type==1?(Mod-1)/(mid<<1):(Mod-1-(Mod-1)/(mid<<1)) , Mod)%Mod;//-
        for(LL R=mid<<1,j=0;j<lim;j+=R){
            LL w = 1;
            for(LL k=0;k<mid;k++){
                LL x=A[j+k] , y=w*A[j+k+mid]%Mod; //-
                A[j+k]=(x+y)%Mod; A[j+k+mid]=(x-y%Mod+Mod)%Mod;
                w=w*Wn%Mod;
            }
        }
    } if(type==1) return ; //reverse(A+1,A+lim); 
    LL INV=Pow(lim,Mod-2,Mod)%Mod;
    for(LL i=0;i<lim;i++) A[i]=A[i]*INV%Mod; return ;
}
LL lim=1;
inline void Mul(LL *A,LL *B,LL *C){
    for(LL i=0;i<M;i++) a1[i]=B[i],b1[i]=C[i];
    for(LL i=M;i<lim;i++) a1[i]=b1[i]=0;
    NTT(a1,lim,1); NTT(b1,lim,1);
    for(LL i=0;i<lim;i++) A[i]=a1[i]*b1[i]%Mod;
    NTT(A,lim,-1);
    for(LL i=lim-1;i>=M-1;i--){
        A[i%(M-1)]=(A[i%(M-1)]+A[i])%Mod; A[i]=0;
    } return ;
}
 
int main(){
    //freopen(".in","r",stdin);
    //freopen(".out","w",stdout);
    N=read(),M=read(),X=read(),S=read(); LL Now=1LL,T=GetN(M);
    for(LL i=0;i<M-1;i++) t[Now]=i,Now=Now*T%M;//cout<<Now<<" "<<T<<endl;
    for(LL i=1;i<=S;i++) {LL x=read()%Mod; if(x) a[t[x]]++; } lim=1; int l=0;
    while(lim<=2*(M-1)) lim<<=1,++l;
    for(LL i=0;i<lim;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));
    memset(b,0,sizeof(b)); b[0]=1;
    while(N){
        if(N&1) Mul(b,a,b);
        Mul(a,a,a); N>>=1;
    } printf("%lld\n",b[t[X]]%Mod);
    return 0;
}

Leave a Reply

Your email address will not be published. Required fields are marked *