BZOJ5306: [Haoi2018]染色
BZOJ5306: [Haoi2018]染色
https://lydsy.com/JudgeOnline/problem.php?id=5306
分析:
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
using namespace std;
#define mod 1004535809
#define N 400050
#define M 10000050
typedef long long ll;
ll A[N],B[N],f[N],g[N];
ll fac[M],inv[M];
ll qp(ll x,ll y) {
ll re=1;for(;y;y>>=1,x=x*x%mod) if(y&1) re=re*x%mod; return re;
}
ll INV(ll x) {return qp(x,mod-2);}
void ntt(ll *a,int len,int flg) {
int i,j,k,t;
ll w,wn,tmp;
for(i=k=0;i<len;i++) {
if(i>k) swap(a[i],a[k]);
for(j=len>>1;(k^=j)<j;j>>=1) ;
}
for(k=2;k<=len;k<<=1) {
t=k>>1; wn=qp(3,(mod-1)/k);
if(flg==-1) wn=INV(wn);
for(i=0;i<len;i+=k) {
w=1;
for(j=i;j<i+t;j++) {
tmp=a[j+t]*w%mod; a[j+t]=(a[j]-tmp)%mod; a[j]=(a[j]+tmp)%mod; w=w*wn%mod;
}
}
}
if(flg==-1) for(tmp=INV(len),i=0;i<len;i++) a[i]=a[i]*tmp%mod;
}
ll w[N],C[N];
ll Cb(ll x,ll y) {return fac[x]*inv[y]%mod*inv[x-y]%mod;}
int main() {
ll n,m,S,u;
scanf("%lld%lld%lld",&n,&m,&S);
u=max(n,max(m,S));
int i;
for(i=0;i<=m;i++) scanf("%lld",&w[i]);
for(fac[0]=i=1;i<=u;i++) fac[i]=fac[i-1]*i%mod;
inv[u]=INV(fac[u]);
for(i=u-1;i>=0;i--) inv[i]=inv[i+1]*(i+1)%mod;
for(i=0;i<=m;i++) if(n-S*i>=0) {
f[i]=fac[n] * qp(inv[S],i)%mod * inv[n-S*i]%mod * qp(m-i,n-S*i)%mod;
}
for(i=0;i<=m;i++) A[i]=f[i]*inv[m-i]%mod;
reverse(A,A+m+1);
for(i=0;i<=m;i++) {
if(i&1) B[i]=-inv[i];
else B[i]=inv[i];
}
int len=1;
while(len<=(m<<1)) len<<=1;
ntt(A,len,1); ntt(B,len,1);
for(i=0;i<len;i++) C[i]=A[i]*B[i]%mod;
ntt(C,len,-1);
for(i=0;i<=m;i++) {
g[i]=fac[m-i]*C[m-i]%mod;
}
ll ans=0;
for(i=0;i<=m;i++) if(n-S*i>=0) {
ans=(ans+w[i]*g[i]%mod*Cb(m,i))%mod;
}
printf("%lld\n",(ans%mod+mod)%mod);
}