題目大意:給定一個長度爲 N 的序列,現有 M 種顏色,選出一些顏色對這個序列進行染色,要求相鄰元素顏色不相同。求最終序列剛好有 K 種不一樣顏色的染色方案數,結果對1e9+7取模。ios
題解:二項式反演c++
代碼以下spa
#include <bits/stdc++.h> using namespace std; typedef long long LL; const LL mod = 1e9 + 7; const int maxn = 1e6 + 10; LL fpow(LL a, LL b) { LL ret = 1 % mod; for (; b; b >>= 1, a = a * a % mod) { if (b & 1) { ret = ret * a % mod; } } return ret; } LL fac[maxn], ifac[maxn]; void prework() { int n = 1e6; fac[0] = fac[1] = 1; for (int i = 2; i <= n; i++) { fac[i] = fac[i - 1] * i % mod; } ifac[n] = fpow(fac[n], mod - 2); for (int i = n - 1; i >= 0; i--) { ifac[i] = ifac[i + 1] * (i + 1) % mod; } } inline LL comb1(int x, int y) { if (y > x) { return 0; } return fac[x] * ifac[x - y] % mod * ifac[y] % mod; } inline LL comb2(int x, int y) { if (y > x) { return 0; } LL ret = 1; for (int i = x; i >= x - y + 1; i--) { ret = ret * i % mod; } return ret * ifac[y] % mod; } int main() { ios::sync_with_stdio(false); cin.tie(0), cout.tie(0); prework(); int T, kase = 0; cin >> T; while (T--) { int n, m, K; cin >> n >> m >> K; auto f = [&](int x) { LL ret = x; return ret * fpow(x - 1, n - 1) % mod; }; LL ans = 0; if (K == 1) { ans = (n == 1) ? 1 : 0; } else { for (int i = 1; i <= K; i++) { if ((K - i) & 1) { ans = (ans - comb1(K, i) * f(i) % mod + mod) % mod; } else { ans = (ans + comb1(K, i) * f(i) % mod) % mod; } } } cout << "Case #" << ++kase << ": " << ans * comb2(m, K) % mod << endl; } return 0; }