个人认为是道很好的组合加容斥练习题。
Solution
考虑将行,列,颜色的限制分开处理。
先限制颜色。
令 $f(i)$ 为只使用 $i$ 种颜色,满足行列限制的方案数,
$$
ans=\sum\limits_{i=0}^c\dbinom{c}{i}(-1)^{c-i}f(i)
$$
再限制列。
令 $g(i,j)$ 为只是用 $i$ 种颜色,只填 $j$ 列的方案数。
$$
f(i)=\sum\limits_{j=0}^m\dbinom{m}{j}(-1)^{c-j}g(i,j)
$$
最后
$$
g(i,j)=((i+1)^j-1)^n
$$
带入求解即可,时间复杂度 $O(mc\log n)$ 。
Code
#include<bits/stdc++.h>
#define N 505
#define int long long
using namespace std;
int read(){
int x=0,w=1;
char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return x*w;
}
const int mod = 1e9+7;
int n,m,c,ans;
int fac[N],ifac[N],a[N],f[N];
int qpow(int x,int k){
int res=1;
while(k){
if(k&1) res=res*x%mod;
x=x*x%mod;k>>=1;
}
return res;
}
void init(){
fac[0]=ifac[0]=1;
for(int i=1;i<=400;++i) fac[i]=fac[i-1]*i%mod;
ifac[400]=qpow(fac[400],mod-2);
for(int i=399;i>=1;--i) ifac[i]=ifac[i+1]*(i+1)%mod;
}
int C(int x,int y){ return fac[x]*ifac[y]%mod*ifac[x-y]%mod; }
signed main(){
init();
n=read();m=read();c=read();
for(int i=0;i<=c;++i)
for(int j=m,opt=1;j>=0;--j,opt*=-1){
int x=opt*C(m,j)*qpow((qpow(i+1,j)-1+mod)%mod,n)%mod;
f[i]=(f[i]+x+mod)%mod;
}
for(int i=c,opt=1;i>=0;--i,opt*=-1) ans=(ans+opt*C(c,i)%mod*f[i]%mod+mod)%mod;
printf("%lld\n",ans);
//for(int i=0;i<=c;++i) cout<<f[i]<<endl;
return 0;
}