题意:n个格子,m种颜色,取k种颜色,恰好使用k种颜色为n个格子上色,相邻格子颜色不同,求方案数,对1e9+7取余。
c(m,k)×k×(k-1)^n-1,这是少于k种颜色上色的情况,不是恰好。
假设出现p (2 <= p <= k-1)种颜色,从k种颜色中选p种进行涂色,方案数为C(k,p) × p × (p-1)^(n-1);
总方案数为C(m,k) × ( k × (k-1)^(n-1) + ∑((-1)^p × C(k, p) × p × (p-1)^(n-1) ) (2 <= p <= k-1);
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long
const int N = 1e6+5;
const int mod = 1e9+7;
ll cm[N], ck[N], inv[N];
ll t, n, m, k;
ll quick_pow(ll a, ll b)///快速幂
{
ll ans = 1;
while(b){
if(b & 1) ans = ans*a%mod;
b >>= 1;
a = a*a%mod;
}
return ans;
}
void get_inv()///逆元
{
for(int i=1; i<N; i++){
inv[i] = quick_pow(i, mod-2);///
}
}
void get_c()///c(m,i) && c(k,i)
{
cm[0] = ck[0] = 1;
for(int i=1; i<=k; i++){///
cm[i] = cm[i-1]%mod * (m-i+1)%mod * inv[i]%mod;///m-i+1
ck[i] = ck[i-1]%mod * (k-i+1)%mod * inv[i]%mod;
}
}
int main()
{
get_inv();//printf("inv %lld\n", inv[2]);
scanf("%d", &t);
for(int cnt=1; cnt<=t; cnt++){
scanf("%d%d%d", &n, &m, &k);
get_c();
ll sign = 1, ans = 0;
for(int i=k; i>=1; i--){
ans = (ans+sign*ck[i]%mod*i%mod*quick_pow((ll)i-1, (ll)n-1)%mod+mod)%mod;
sign = -sign;///奇加偶减
}
ans = ans*cm[k]%mod;///m选k个
printf("Case #%d: %lld\n", cnt, ans);
}
return 0;
}