记录编号 298531 评测结果 AAAAAAAAAA
题目名称 [SDOI 2015] 序列统计 最终得分 100
用户昵称 GravatarTenderRun 是否通过 通过
代码语言 C++ 运行时间 10.340 s
提交时间 2016-08-21 23:18:30 内存使用 0.65 MiB
显示代码纯文本
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int N=32768,G=3;
const int MOD=1004535809;
int g,n,m,x,s,pos[N],num[N];
int Qpow(int x,int k,int mod){
	long long ret=1;
	while(k){
		if(k&1)ret=1ll*ret*x%mod;
		x=1ll*x*x%mod;k>>=1;
	}
	return ret;
}

void Rader(int *a,int len){
	for(int i=1,j=len>>1;i<len-1;i++){
		if(i<j)swap(a[i],a[j]);
		int k=len>>1;
		while(j>=k){
			j-=k;
			k>>=1;
		}
		j+=k;
	}
}

void NTT(int *a,int len,int on){
	Rader(a,len);
	for(int h=2,wn;h<=len;h<<=1){
		if(on==1)wn=Qpow(G,(MOD-1)/h,MOD);
		else wn=Qpow(G,MOD-1-(MOD-1)/h,MOD);
		for(int j=0;j<len;j+=h){
			int w=1,x,y;
			for(int k=j;k<j+(h>>1);k++){
				x=a[k];y=1ll*a[k+(h>>1)]*w%MOD;
				a[k]=(x+y)%MOD;a[k+(h>>1)]=(x-y+MOD)%MOD;
				w=1ll*w*wn%MOD;
			}
		}
	}
	if(on==-1){
		int inv=Qpow(len,MOD-2,MOD);
		for(int i=0;i<len;i++)
			a[i]=1ll*a[i]*inv%MOD;
	}	
}

int f[N],r[N],l=N/2;
void Solve(){
	for(int i=0;i<N;i++)
		r[i]=f[i];n-=1;
	while(n){
		NTT(f,N,1);
		if(n&1){
			NTT(r,N,1);
			for(int i=0;i<N;i++)r[i]=1ll*r[i]*f[i]%MOD;
			NTT(r,N,-1);
			for(int i=m-1;i<N;i++)(r[i%(m-1)]+=r[i])%=MOD,r[i]=0;
		}
		for(int i=0;i<N;i++)f[i]=1ll*f[i]*f[i]%MOD;
		NTT(f,N,-1);
		for(int i=m-1;i<N;i++)(f[i%(m-1)]+=f[i])%=MOD,f[i]=0;
		n>>=1;
	}
	printf("%d\n",r[pos[x]]);
}

void Solve_Zero(){int cnt=0,ans;
	for(int i=1;i<=s;i++)if(!num[i])cnt++;
	ans=Qpow(s,n,MOD)-Qpow(s-cnt,n,MOD);
	printf("%d\n",ans);
}
int main(){
	freopen("sdoi2015_sequence.in","r",stdin);
	freopen("sdoi2015_sequence.out","w",stdout);
	scanf("%d%d%d%d",&n,&m,&x,&s);
	for(int i=1;i<=s;i++)
		scanf("%d",&num[i]);
	if(!x)Solve_Zero();
	for(g=1;g<m;g++){int i;
		for(i=1;i<m-1;i++)
			if(Qpow(g,i,m)==1)
				break;
		if(i==m-1&&Qpow(g,m-1,m)==1)break;		
	}
	for(int i=1;i<m;i++)
		pos[Qpow(g,i,m)]=i%(m-1);
	for(int i=1;i<=s;i++)
		if(num[i])f[pos[num[i]]]++;
	Solve();
	return 0;
}