考虑容斥,即枚举没有涂色的行、列和没有用的颜色。答案是
∑i=0n∑j=0m∑k=0c(−1)i+j+k(ni)(mj)(ck)(c−k+1)(n−i)(m−j)
复杂度是 O(nmc) ,但是我们还可以进一步优化。把所有关于 m 的项提出来,我们得到
根据二项式定理,右边一部分就是
[(c−k+1)n−i−1]m
这样复杂度就是 O(min(n,m)clogmax(n,m)) 。
#include<cstdio>
#include<algorithm>
using namespace std;
#define LL long long
const int p=1000000007,maxn=410;
int n,m,c,C[maxn][maxn];
int pow(int base,int k)
{
int ret=1;
for (;k;k>>=1,base=(LL)base*base%p)
if (k&1) ret=(LL)ret*base%p;
return ret;
}
int inc(int x,int y)
{
x+=y;
return x>=p?x-p:x;
}
int dec(int x,int y)
{
x-=y;
return x<0?x+p:x;
}
int main()
{
int ans=0,mx;
scanf("%d%d%d",&n,&m,&c);
mx=max(n,c);
for (int i=0;i<=mx;i++) C[i][0]=1;
for (int i=0;i<=mx;i++)
for (int j=1;j<=i;j++)
C[i][j]=inc(C[i-1][j],C[i-1][j-1]);
for (int i=0;i<=n;i++)
for (int k=0;k<=c;k++)
if (i+k&1) ans=dec(ans,(LL)C[n][i]*C[c][k]%p*pow(dec(pow(c-k+1,n-i),1),m)%p);
else ans=inc(ans,(LL)C[n][i]*C[c][k]%p*pow(dec(pow(c-k+1,n-i),1),m)%p);
printf("%d\n",ans);
}