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);
}

猜你喜欢

转载自www.cnblogs.com/suika/p/10205129.html