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);
}
posted @ 2019-01-01 16:32  fcwww  阅读(157)  评论(0编辑  收藏  举报