题目大意:
用k种颜色涂 n*m 的矩形,要求 如果 1~i 和 i+1~m 所用的颜色种类一样多,不要求颜色一样、
思路:
可以推出 第一列和第m列所用的颜色数量是一样的。
证明 :如果a[1~1]=i a[m~m]=j (i<j)
那么a[1~1]=i<j<=a[2~m] 所以不满足
然后中间的m-2列 是不能出现新颜色的。也就是必须是第一列和第m列的颜色不然会导致两边不相等了。
用dp[i] 表示用i种颜色且必须是i种颜色涂在n个格子上的方式。
那么 dp[i] = i^n-segma(C(i,j)*dp[j]) 1<=j<i 也就是减去只涂了少于i种的情况
然后我们开始处理,
当m==1的时候 就是k^n
当m==2的时候 左边i种 右边 i种 就是 (C(k,i)*dp[i])^2...
当m==3的时候
要枚举相同的颜色的数量i 和不同的颜色的数量j
第一列在k个里选i个 然后在k-i个里选择选择j个 第m列则要在k-i-j里再选j个
然后再涂上去 就是乘以 dp[i+j]...
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
typedef long long LL;
using namespace std;
const LL mod=1000000007;
LL fac[1000005]={1},rev[1000005]={1};
LL dp[1005];
LL pow_mod(LL a,LL i,LL n)
{
if(i==0)return 1%n;
LL temp=pow_mod(a,i>>1,n);
temp=temp*temp%n;
if(i&1)temp=temp*a%n;
return temp;
}
void init()
{
for(int i=1;i<=1000000;i++)
fac[i]=fac[i-1]*i%mod,rev[i]=pow_mod(fac[i],mod-2,mod);
}
LL C(int n,int m)
{
return (fac[n]*rev[m]%mod)*rev[n-m]%mod;
}
int main()
{
init();
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
if(m==1)
{
printf("%I64d\n",pow_mod(k,n,mod));
return 0;
}
for(int i=1;i<=n && i<=k;i++)
{
dp[i]=pow_mod(i,n,mod);
for(int j=1;j<i;j++)
{
dp[i]=(dp[i]-C(i,j)*dp[j]%mod)+mod;
dp[i]%=mod;
}
}
LL ans=0;
if(m==2)
{
for(int i=1;i<=n && i<=k;i++)
{
ans=(ans+(((dp[i]*dp[i]%mod)*C(k,i)%mod)*C(k,i))%mod)%mod;
}
printf("%I64d\n",ans);
}
else
{
for(int i=1;i<=n && i<=k;i++)
{
for(int j=0;2*j+i<=k && i+j<=n;j++)
{
LL tmp=dp[i+j]*dp[i+j]%mod;
tmp=((tmp*C(k,i)%mod)*C(k-i,j)%mod)*C(k-i-j,j)%mod;
tmp=(tmp*pow_mod(i,n*(m-2),mod))%mod;
ans=(ans+tmp)%mod;
}
}
printf("%I64d\n",ans);
}
return 0;
}