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

传送门


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

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

考虑 d = 1 d=1 d=1的时候,由于时间不同,考虑每个复读机的 E G F EGF EGF就是 F ( x ) = ∑ i = 0 ∞ [ d ∣ i ] x i i ! F(x)=\sum_{i=0}^{\infty}[d|i]\frac{x^i}{i!} F(x)=i=0[di]i!xi

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

F ( x ) = ∑ i = 0 ∞ 1 d ∑ j = 0 d − 1 ( w d i ) j x i i ! = ∑ i = 0 ∞ 1 d ∑ j = 0 d − 1 ( w d j x ) i i ! = 1 d ∑ i = 0 ∞ e w d i x \begin{aligned} F(x)&=&&\sum_{i=0}^{\infty}\frac{1}{d}\sum_{j=0}^{d-1}(w_d^i)^j\frac{x^i}{i!}\\ &=&&\sum_{i=0}^{\infty}\frac 1 d\sum_{j=0}^{d-1}\frac{(w_d^jx)^i}{i!}\\ &=&&\frac 1 d\sum_{i=0}^{\infty}e^{w_d^ix} \end{aligned} F(x)===i=0d1j=0d1(wdi)ji!xii=0d1j=0d1i!(wdjx)id1i=0ewdix

d = 2 d=2 d=2
F ( x ) = e x + e − x 2 a n s = ( e x + e − x 2 ) k \begin{aligned} F(x)=\frac{e^x+e^{-x}}{2}\\ ans=(\frac{e^x+e^{-x}}{2})^k\\ \end{aligned} F(x)=2ex+exans=(2ex+ex)k

暴力二项式展开即可

d = 3 d=3 d=3
w n = g w_n=g wn=g
F ( x ) = e x + e g x + e g 2 x 3 F(x)=\frac{e^x+e^{gx}+e^{g^2x}}{3} F(x)=3ex+egx+eg2x
由于此时 k ≤ 1000 k\leq 1000 k1000
仍然暴力展开即可

#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;
	}
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值