题意: 用m种颜色染一个线性格子,相邻格子颜色不同,问恰好染k种颜色的方案数.
至多用k个颜色的方案数目为 k∗(k−1)k * (k - 1)k∗(k−1)
但是要求的是恰好k个颜色,考虑容斥
AiA_iAi 表示不用i号颜色i号颜色i号颜色 然后考虑对立面,
∣A1‾∩A2‾∩...∩Ak‾∣| \overline{A_1} \cap \overline{A_2} \cap...\cap\overline{A_k} | ∣A1∩A2∩...∩Ak∣ =k∗(k−1)n−1−∣A1∪A2∪...∪Ak∣=k * (k - 1)^{n-1} -|{A_1}\cup{A_2}\cup{...}\cup{A_k}|=k∗(k−1)n−1−∣A1∪A2∪...∪Ak∣
=k∗(k−1)n−1−∑∣Ai∣+∑∣Ai∩Aj∣+...+(−1)k∑∣A1∩A2∩...∩Ak∣= k*(k-1)^{n-1}-\sum|A_i|+\sum|A_i\cap A_j|+...+(-1)^k\sum|A_1 \cap A_2\cap...\cap A_k|=k∗(k−1)n−1−∑∣Ai∣+∑∣Ai∩Aj∣+...+(−1)k∑∣A1∩A2∩...∩Ak∣
∑∣Ai∣=Ck1∗(k−1)∗(k−2)n−1\sum|A_i| = C_k^1*(k-1)*(k-2)^{n-1}∑∣Ai∣=Ck1∗(k−1)∗(k−2)n−1
∑∣Ai1∩Ai2∩...∩Aij∣=Ckj∗(k−j)∗(k−j−1)n−1\sum|A_{i_1} \cap A_{i_2}\cap...\cap A_{i_j}| = C_k^{j}*(k-j)*(k-j-1)^{n-1}∑∣Ai1∩Ai2∩...∩Aij∣=Ckj∗(k−j)∗(k−j−1)n−1
ans=∣A1‾∩A2‾∩...∩Ak‾∣∗Cmkans=| \overline{A_1} \cap \overline{A_2} \cap...\cap\overline{A_k} |*C_m^kans=∣A1∩A2∩...∩Ak∣∗Cmk
CmkC_{m}^{k}Cmk 可以利用递推得到:Cmk=Cmk−1∗m−k+1kC_{m}^{k} = C_{m}^{k-1} * \frac {m-k+1}{k}Cmk=Cmk−1∗km−k+1
代码
/***********************************************
Author :lzs
Created Time :2018年10月19日 星期五 17时49分21秒
File Name :Color.cpp
************************************************/
#include <bits/stdc++.h>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <string>
#include <math.h>
#include <stack>
#include <vector>
#include <queue>
#include <set>
#include <map>
using namespace std;
#define rep(i, l, r) for(int i = l; i < r; i++)
#define per(i, r, l) for(int i = r; i >= l; i--)
#define dbgln(...) cerr<<"["<<#__VA_ARGS__":"<<(__VA_ARGS__)<<"]"<<"\n"
#define dbg(...) cerr<<"["<<#__VA_ARGS__":"<<(__VA_ARGS__)<<"]"
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int>pii;
const int N = (int) 1e6 + 20;
const int M = (int) 1e6 + 11;
const int MOD = (int) 1e9 + 7;
const int INF = (int) 0x3f3f3f3f;
const ll INFF = (ll) 0x3f3f3f3f3f3f3f3f;
/*-----------------------------------------------------------*/
int Pow(int a, int b, int c = MOD){
int s = 1; a %= c;
while(b){
if(b & 1) s = s * 1ll * a % c;
b >>= 1;
a = a * 1ll * a % c;
}
return s;
}
int fac[N], inv[N], in[N];
void ini(int n){
fac[0] = 1;
for(int i = 1; i < n; i++) fac[i] = i * 1ll * fac[i - 1] % MOD, in[i] = Pow(i, MOD - 2);
inv[n - 1] = Pow(fac[n - 1], MOD - 2); inv[0] = 1;
for(int i = n - 2; i > 0; i--) inv[i] = inv[i + 1] * 1ll * (i + 1) % MOD;
}
int C(int n, int m){
if(n < m) return 0;
return fac[n] * 1ll * inv[n - m] % MOD * inv[m] % MOD;
}
int main(){
ini(1000000 + 10);
int T; scanf("%d" ,&T);
for(int cas = 1; cas <= T; cas++){
int n, m, k; scanf("%d%d%d", &n, &m, &k);
int cmk = 1;
for(int i = 1; i <= k; i++)
cmk = cmk * 1ll * (m - i + 1) % MOD * in[i] % MOD;
ll ans = k * 1ll * Pow(k - 1, n - 1) % MOD;
int cur = -1;
for(int i = 1; i < k; i++){
ans += cur * 1ll * C(k, i) * (k - i) % MOD * Pow(k - i - 1, n - 1) % MOD;
ans = (ans + MOD) % MOD;
cur = -cur;
}
ans = ans * 1ll * cmk % MOD;
printf("Case #%d: %lld\n", cas, ans);
}
return 0;
}