记录编号 163801 评测结果 AAAAAAAAAA
题目名称 [SDOI 2015] 序列统计 最终得分 100
用户昵称 Gravatarcstdio 是否通过 通过
代码语言 C++ 运行时间 2.845 s
提交时间 2015-05-26 15:51:58 内存使用 0.85 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long LL;
const int SIZE=20010;
LL Real_Mod(LL a,LL m){
	a%=m;
	if(a<0) a+=m;
	return a;
}
LL Quick_Pow(LL a,LL n,LL m){
	LL ans=1;
	while(n){
		if(n&1) ans=Real_Mod(ans*a,m);
		a=Real_Mod(a*a,m);
		n>>=1;
	}
	return ans;
}
LL Inverse(LL a,LL m){//要求a是质数
	return Quick_Pow(a,m-2,m);
}
class Poly{
public:
	static const LL MOD=1004535809;
	static const LL G=3;
	int n;
	LL s[SIZE];
	void print(void)const{
		for(int i=0;i<n;i++){cout<<s[i]<<" ";}cout<<endl;
	}
	void clear(void){
		n=0;
		memset(s,0,sizeof(s));
	}
	inline void Rader_Transform(void){
		int j=0,k;
		for(int i=0;i<n;i++){
			if(j>i) swap(s[j],s[i]);
			k=n;
			while(j&(k>>=1)) j&=~k;
			j|=k;
		}
	}
	void NTT(bool type){//type=1是系数求点,type=0是点求系数
		Rader_Transform();
		for(int step=1;step<n;step<<=1){
			LL wn=Quick_Pow(G,(MOD-1)/(step<<1),MOD);
			if(!type) wn=Quick_Pow(G,MOD-1-(MOD-1)/(step<<1),MOD);
			LL wk=1;
			for(int k=0;k<step;k++){
				for(int Ek=k;Ek<n;Ek+=step<<1){
					int Ok=Ek+step;
					LL t=Real_Mod(wk*s[Ok],MOD);
					s[Ok]=Real_Mod(s[Ek]-t,MOD);
					s[Ek]=Real_Mod(s[Ek]+t,MOD);
				}
				wk=Real_Mod(wn*wk,MOD);
			}
		}
		if(!type){
			LL inv=Inverse(n,MOD);
			for(int i=0;i<n;i++) s[i]=Real_Mod(s[i]*inv,MOD);
		}
	}
	void operator *= (const Poly &a){
		static Poly b;
		b=a;
		int m=1;
		while(m<n+b.n) m<<=1;
		n=b.n=m;
		NTT(true);
		b.NTT(true);
		for(int i=0;i<n;i++) s[i]=Real_Mod(s[i]*b.s[i],MOD);
		NTT(false);
	}
	void Normalize(int P){//质数P的原根表示
		for(int i=n-1;i>=P-1;i--){
			s[i%(P-1)]=Real_Mod(s[i%(P-1)]+s[i],MOD);
			s[i]=0;
		}
		n=P-1;
	}
};
int N,M,X,S,rt;
Poly A;
Poly ans;
int ind[SIZE];
Poly Quick_Pow(Poly a,int n){
	Poly ans;
	ans.clear();
	ans.n=1;
	ans.s[0]=1;
	while(n){
		if(n&1) ans*=a;
		a*=a;
		ans.Normalize(M);
		a.Normalize(M);
		n>>=1;
	}
	return ans;
}
bool Is_Root(int x){
	for(int i=2;i*i<=M-1;i++){
		if((M-1)%i==0){
			if(Quick_Pow(x,i,M)==1) return false;
			if(Quick_Pow(x,(M-1)/i,M)==1) return false;
		}
	}
	return true;
}
int Find_Root(void){
	for(int i=2;i<M;i++){
		if(Is_Root(i)) return i;
	}
	return -1;
}
void Work(void){
	ans=Quick_Pow(A,N);
	printf("%lld\n",ans.s[ind[X]]);
}
void Init(void){
	scanf("%d%d%d%d",&N,&M,&X,&S);
	rt=Find_Root();
	for(int i=0,now=1;i<M-1;i++,now=Real_Mod(now*rt,M)) ind[now]=i;
	A.clear();
	A.n=M-1;
	int t;
	for(int i=1;i<=S;i++){
		scanf("%d",&t);
		t%=M;
		if(t==0) continue;
		A.s[ind[t]]++;
	}
}
int main(){
	freopen("sdoi2015_sequence.in","r",stdin);
	freopen("sdoi2015_sequence.out","w",stdout);
	Init();
	Work();
	return 0;
}