有n朵花排成一列,m种颜色,给这些花染色,使得恰好有k种颜色,且相邻的花颜色不同,问有多少种染色法。
首先必须从m种颜色中选出k种,这部分有C(m,k)种选法。然后第一朵花可以染成k种颜色,后面的所有花都能染成k-1种颜色,也就是k*(k-1)*...*(k-1)。但是这样不能保证整个过程中k种颜色全部用到了。于是需要根据容斥原理做一下处理,减去用了k-1种颜色的情况,加上用了k-2种颜色的情况......另外计算过程中用到了组合数,可以逆元+暴力计算出来。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int mod = 1e9+7;
const int maxk = 1000010;
ll fac[maxk];
ll inv[maxk];
ll Pow(ll a,int n){
ll re=1;
while(n){
if(n&1){
re*=a;
re%=mod;
}
a*=a;
a%=mod;
n>>=1;
}
return re;
}
//组合数
ll C(int n,int k){
if(n<=1000000){
ll res=fac[n]*inv[k];
res%=mod;
res*=inv[n-k];
res%=mod;
return res;
}
ll res=inv[k];
for(int i=0;i<k;i++){
res*=(n-i);
res%=mod;
}
return res;
}
void init(){
fac[0]=1;
for(int i=1;i<maxk;i++){
fac[i]=fac[i-1]*i;
fac[i]%=mod;
}
inv[0]=1; //注意这个不能漏
for(int i=1;i<maxk;i++){//费马小定理计算阶乘的逆元
inv[i]=Pow(fac[i],mod-2);
}
}
int main(){
init();
int t;
cin>>t;
int cas=0;
while(t--){
cas++;
ll n,m,k;
cin>>n>>m>>k;
ll part1 = C(m,k);
ll part2 = k*Pow(k-1,n-1);
part2%=mod;
int sign = -1;
for(ll i=k-1;i>1;i--){
ll tmp = i*Pow(i-1,n-1);
tmp%=mod;
tmp*=C(k,i);
tmp%=mod;
tmp*=sign;
part2+=tmp;
part2+=mod;
part2%=mod;
sign=-sign;
}
ll ans = part1*part2;
ans %= mod;
printf("Case #%d: ",cas);
cout<<ans<<endl;
}
return 0;
}