题目链接:这里
题意:首先有T组数据,每组数据有 3 个数 n, m, k,分别代表一共有 n 个方格,m种颜色,而我们要 恰好(注意是恰好) 使用 k 中颜色对这些方格进行涂色,并且保证的是每两个相邻的方格的颜色必须是不一样的。
解法:m种颜色选k种,所以有C(m,k),对于选出的k种颜色去给n个人涂色,对于第一个人有k种,第二个人有k-1种,第三个人k-1种。。。。。所以总共是k*(k-1)^(n-1)种。然而不要以为这样就好了,因为这样算并不能保证是一定用了k种颜色的,可能只是选了k种其中的2,3,4,,,,k-1种,所以要用容斥原理来去重,所以最后的式子就是C(m,k) × ( k × (k-1)^(n-1) + ∑((-1)^p × C(k, p) × p × (p-1)^(n-1) ) (2 <= p <= k-1)。然后窝们为了计算这个式子,必须线形预处理逆元和C(i, m)和C(j, k)其中 i <= m 和 j <= k。线形逆元不懂可以看这位大佬的
然后组合数递推的式子是怎么样的呢?
//LA 7040
#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 7;
typedef long long LL;
LL inv[maxn], cm[maxn], ck[maxn], n, m, k;
LL powmod(LL a, LL n){
LL res = 1;
while(n){
if(n & 1) res = res * a % mod;
a = a * a % mod;
n >>= 1LL;
}
return res;
}
void init(){
inv[1] = 1;
for(long long i = 2; i <= 1000006; i++) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
}
void pre_deal(){
cm[0] = ck[0] = 1;
for(long long i = 1; i <= k; i++){
cm[i] = cm[i-1]%mod*(m-i+1)%mod*inv[i]%mod;
ck[i] = ck[i-1]%mod*(k-i+1)%mod*inv[i]%mod;
}
}
int main()
{
init();
int T, ks = 0; scanf("%d", &T); while(T--){
scanf("%lld%lld%lld", &n, &m, &k);
pre_deal();
int t = 1;
LL ans = 0;
for(long long i = k; i >= 1; i--){
ans = (ans + t * i * ck[i] % mod * powmod(i - 1, n - 1) % mod + mod) % mod;
t = -t;
}
ans = ans * cm[k] % mod;
printf("Case #%d: %lld\n", ++ks, ans);
}
return 0;
}