bzoj5306:[Haoi2018]染色

传送门

$f(i)$为出现次数为$S$的颜色种类至少有$i$种的涂色方案

$f(i)=\binom{m}{i}\frac{n!}{(S!)^i(n-iS)!}(m-i)^{n-iS}$

$\frac{(iS)!}{(iS-S)!S!}\frac{(iS-S)!}{(iS-2S)!S!}\frac{(iS-2S)!}{(iS-3S)!S!}...\\ \frac{(iS)!}{S!}\frac{1}{S!}\frac{1}{S!}...\\ \frac{(iS)!}{(S!)^i}$

$ans(i)=\sum_{j=i}^{min(m,n/s)}(-1)^{j-i}\binom{j}{i}f(j)$

$ans(i)=\sum_{j=i}^{min(m,n/s)}(-1)^{j-i}\frac{j!}{i!(j-i)!}f(j)\\ i!*ans(i)=\sum_{j=i}^{min(m,n/s)}\frac{(-1)^{j-i}}{(j-i)!}f(j)j!\\$

$A(x)=\frac{(-1)^x}{x!}\\ B(x)=f(x)x!$

$i!*ans(i)=\sum_{j=i}^{min(m,n/s)}A(j-i)B(j)\\ i!*ans(i)=\sum_{j=0}^{min(m,n/s)-i}A(j)B(j+i)\\$

$i!*ans(i)=\sum_{j=0}^{min(m,n/s)-i}A(j)B(min(m,n/s)-j-i)\\$

$D$是做完之后的多项式
$ans=\sum_{i=0}^{min(m,n/s)}\frac{w(i)D(i)}{i!}$

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
char ch; bool ok;
for(ok=0,ch=getchar(); !isdigit(ch); ch=getchar()) if(ch=='-') ok=1;
for(x=0; isdigit(ch); x=x*10+ch-'0',ch=getchar()); if(ok) x=-x;
}
const int maxn=5e5+10,maxm=1e7+10,mod=1004535809,g=3,gi=334845270;
#define rg register
int tot,r[maxm],len,n,m,ans,s,w[maxm],N,f[maxm],A[maxm],B[maxm],fac[maxm],inv[maxm];
int mul(int x,int y){return 1ll*x*y-1ll*x*y/mod*mod;}
int del(int x,int y){return x-y<0?x-y+mod:x-y;}
int mi(int a,int b){
int ans=1;
while(b){
if(b&1)ans=mul(ans,a);
b>>=1,a=mul(a,a);
}
return ans;
}
void ntt(int *a,int f){
for(rg int i=0;i<N;i++)if(r[i]>i)swap(a[i],a[r[i]]);
for(rg int i=1;i<N;i<<=1){
int wn=mi(f?g:gi,(mod-1)/(i<<1));
for(rg int j=0;j<N;j+=(i<<1)){
int w=1;
for(rg int k=0;k<i;k++){
int x=a[j+k],y=mul(w,a[j+k+i]);
}
}
}
if(f)return ;int inv=mi(N,mod-2);
for(rg int i=0;i<N;i++)a[i]=mul(a[i],inv);
}
int C(int x,int y){return mul(fac[x],mul(inv[y],inv[x-y]));}
int main()
{
fac[0]=inv[0]=1;int now=max(n,m);
for(rg int i=1;i<=now;i++)fac[i]=mul(fac[i-1],i);
inv[now]=mi(fac[now],mod-2);
for(rg int i=now-1;i;i--)inv[i]=mul(inv[i+1],i+1);