【UOJ#450】【集训队作业2018】—复读机(单位根反演+生成函数)

传送门


数据范围很明显是要我们分情况讨论

d=1d=1的时候答案显然就是knk^n

考虑d=1d=1的时候,由于时间不同,考虑每个复读机的EGFEGF就是F(x)=i=0[di]xii!F(x)=sum_{i=0}^{infty}[d|i]frac{x^i}{i!}

[di][d|i]单位根反演一下

F(x)=i=01dj=0d1(wdi)jxii!=i=01dj=0d1(wdjx)ii!=1di=0ewdix egin{aligned} F(x)&=&&sum_{i=0}^{infty}frac{1}{d}sum_{j=0}^{d-1}(w_d^i)^jfrac{x^i}{i!}\ &=&&sum_{i=0}^{infty}frac 1 dsum_{j=0}^{d-1}frac{(w_d^jx)^i}{i!}\ &=&&frac 1 dsum_{i=0}^{infty}e^{w_d^ix} end{aligned}

d=2d=2
F(x)=ex+ex2ans=(ex+ex2)k egin{aligned} F(x)=frac{e^x+e^{-x}}{2}\ ans=(frac{e^x+e^{-x}}{2})^k\ end{aligned}

暴力二项式展开即可

d=3d=3
wn=gw_n=g
F(x)=ex+egx+eg2x3F(x)=frac{e^x+e^{gx}+e^{g^2x}}{3}
由于此时k1000kleq 1000
仍然暴力展开即可

#include<bits/stdc++.h>
using namespace std;
const int RLEN=1<<20|1;
inline char gc(){
	static char ibuf[RLEN],*ib,*ob;
	(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ib==ob)?EOF:*ib++;
}
#define gc getchar
inline int read(){
	char ch=gc();
	int res=0,f=1;
	while(!isdigit(ch))f^=ch=='-',ch=gc();
	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
	return f?res:-res;
}
const int mod=19491001,g=7;
inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
inline void Add(int &a,int b){a=add(a,b);}
inline int dec(int a,int b){return a>=b?a-b:a-b+mod;}
inline void Dec(int &a,int b){a=dec(a,b);}
inline int mul(int a,int b){return 1ll*a*b>=mod?1ll*a*b%mod:a*b;}
inline void Mul(int &a,int b){a=mul(a,b);}
inline int ksm(int a,int b,int res=1){for(;b;b>>=1,a=mul(a,a))(b&1)?(res=mul(res,a)):0;return res;}
int n,d,k;
const int N=500005;
int fac[N],ifac[N];
inline void init(){
	fac[0]=ifac[0]=1;
	for(int i=1;i<N;i++)fac[i]=mul(fac[i-1],i);
	ifac[N-1]=ksm(fac[N-1],mod-2);
	for(int i=N-2;i;i--)ifac[i]=mul(ifac[i+1],i+1);
}
inline int C(int n,int m){
	if(n<m)return 0;
	return mul(fac[n],mul(ifac[m],ifac[n-m]));
}
int main(){
	init();
	n=read(),k=read(),d=read();
	if(d==1){cout<<ksm(k,n);return 0;}
	else if(d==2){
		int res=0;
		for(int i=0;i<=k;i++)Add(res,mul(C(k,i),ksm(dec(2*i,k),n)));
		Mul(res,ksm(ksm(2,k),mod-2));
		cout<<res;
	}
	else{
		int res=0,w=ksm(g,(mod-1)/3);
		for(int i=0;i<=k;i++){
			int tmp=0;
			for(int j=0;j<=k-i;j++){
				Add(tmp,mul(C(k-i,j),ksm(1ll*(1ll*i+1ll*w*j%mod+1ll*w*w%mod*(k-i-j)%mod)%mod,n)));
			}
			Add(res,mul(tmp,C(k,i)));
		}
		Mul(res,ksm(ksm(3,k),mod-2));
		cout<<res;
	}
}
原文地址:https://www.cnblogs.com/stargazer-cyk/p/12328815.html