【UOJ#450】【集训队作业2018】—复读机(单位根反演+生成函数)
数据范围很明显是要我们分情况讨论
的时候答案显然就是
考虑的时候,由于时间不同,考虑每个复读机的就是
把单位根反演一下
当
暴力二项式展开即可
当时
设
由于此时
仍然暴力展开即可
#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;
}
}