传送门
题意简述:
用ccc中颜色给一个n∗mn*mn∗m的方格染色,每个格子可涂可不涂,问最后每行每列都涂过色且ccc中颜色都出现过的方案数。
思路:
令fi,j,kf_{i,j,k}fi,j,k表示至少有iii行没涂色,至少有jjj列没涂色,至少有ccc种颜色没涂色的方案数。
于是fi,j,k=CniCmjCck(c−k+1)(n−i)(m−j)f_{i,j,k}=C_n^iC_m^jC_c^k(c-k+1)^{(n-i)(m-j)}fi,j,k=CniCmjCck(c−k+1)(n−i)(m−j)
容斥一下即可。
注意算最后一项的时候每次先预处理。
代码:
#include<bits/stdc++.h>
#define ri register int
using namespace std;
typedef long long ll;
const int N=405,mod=1e9+7,mod1=1e9+6;
int ans=0,fac[N],ifac[N],n,m,c,a[N],mult[N*N];
inline int add(const int&a,const int&b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(const int&a,const int&b){return a>=b?a-b:a-b+mod;}
inline int mul(const int&a,const int&b){return (ll)a*b%mod;}
inline int C(int n,int m){return mul(mul(fac[n],ifac[m]),ifac[n-m]);}
inline void init(){
int up=max(n,max(m,c));
fac[0]=fac[1]=ifac[0]=ifac[1]=1;
for(ri i=2;i<=up;++i)fac[i]=mul(fac[i-1],i),ifac[i]=mul(ifac[mod-mod/i*i],mod-mod/i);
for(ri i=2;i<=up;++i)ifac[i]=mul(ifac[i],ifac[i-1]);
}
int main(){
freopen("lx.in","r",stdin);
cin>>n>>m>>c;
init();
for(ri k=0,tmp;k<=c;++k){
mult[0]=1;
for(ri i=1;i<=n*m;++i)mult[i]=mul(mult[i-1],c-k+1);
for(ri i=0;i<=n;++i)for(ri j=0;j<=m;++j){
tmp=mul(mul(C(n,i),C(m,j)),mul(C(c,k),mult[(n-i)*(m-j)]));
ans=(i+j+k)&1?dec(ans,tmp):add(ans,tmp);
}
}
cout<<ans;
return 0;
}