P4491 [HAOI2018] 染色 的代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=2e7;
const int mod=1004535809;
const int mg=3;
int N;
int W[maxn+5];
int F[maxn+5];
int A[maxn+5],B[maxn+5];
int G[maxn+5],ans;
int fac[maxn+5],inv[maxn+5];
inline int Fpow(int x,int y){
int res=1;
for(x%=mod;y;x=x*x%mod,y>>=1)
if(y&1) res=res*x%mod;
return res;
}
namespace NTT{
int n,m;
int a[maxn+5],b[maxn+5];
int r[maxn+5];
int tp=1,ltp,itp;
inline void Ntt(int f[],int typ){
for(int i=0;i<tp;i++)
if(i<r[i]) swap(f[i],f[r[i]]);
for(int i=1;i<tp;i<<=1){
int tmp=i<<1,wn=(mod-1)/tmp;
if(typ==1) wn=Fpow(mg,wn);
else wn=Fpow(mg,mod-1-wn);
for(int j=0;j<tp;j+=tmp){
int w=1;
for(int k=0;k<i;k++){
int x=f[j+k],y=w*f[i+j+k]%mod;
f[j+k]=(x+y)%mod;
f[i+j+k]=((x-y)%mod+mod)%mod;
w=w*wn%mod;
}
}
}
}
void Work(int A[],int B[],int C[]){
n=m=N;
for(int i=0;i<=n;i++) a[i]=(A[i]+mod)%mod;
for(int i=0;i<=m;i++) b[i]=(B[i]+mod)%mod;
while(tp<n+m+1) tp<<=1,ltp++;
itp=Fpow(tp,mod-2);
for(int i=0;i<tp;i++)
r[i]=(r[i>>1]>>1)|((i&1)<<(ltp-1));
Ntt(a,1),Ntt(b,1);
for(int i=0;i<tp;i++)
a[i]=a[i]*b[i]%mod;
Ntt(a,-1);
for(int i=0;i<tp;i++)
a[i]=a[i]*itp%mod;
for(int i=0;i<=n+m;i++)
C[i]=(a[i]+mod)%mod;
}
}
int n,m,S;
inline void Init(){
fac[0]=1;
for(int i=1;i<=maxn;i++) fac[i]=fac[i-1]*i%mod;
inv[maxn]=Fpow(fac[maxn],mod-2);
for(int i=maxn-1;i>=0;i--) inv[i]=inv[i+1]*(i+1)%mod;
}
inline int C(int x,int y){
return fac[x]*inv[x-y]%mod*inv[y]%mod;
}
signed main(){
Init();
scanf("%lld%lld%lld",&n,&m,&S);
N=min(n/S,m);
for(int i=0;i<=m;i++)
scanf("%lld",&W[i]);
for(int i=0;i<=N;i++){
F[i]=C(m,i)*C(n,i*S)%mod*fac[i*S]%mod
*Fpow(inv[S],i)%mod*Fpow(m-i,n-i*S)%mod;
}
for(int i=0;i<=N;i++){
A[i]=Fpow(-1,i)*inv[i];
B[N-i]=F[i]*fac[i]%mod;
}
NTT::Work(A,B,G);
for(int i=0;i<=N;i++)
ans=(ans+G[N-i]*inv[i]%mod*W[i])%mod;
printf("%lld",ans);
return 0;
}