King's Colors 題解
阿新 • • 發佈:2021-12-13
link
題意:給出一個含有 \(n\) 個節點的樹,以及 \(k\) 個顏色,詢問有多少種方式正好用 \(k\) 個顏色給樹染色,並且任意兩個相鄰的節點顏色不同。
拿到這道題,我剛開始考慮的是從兒子開始考慮父親。但是這樣會出現一個問題,兒子顏色重複的數量決定這個父親的取值數量的多少。於是不好控制。
但是其實換個角度(trick),考慮從父親開始考慮兒子,發現兒子有 \(k-1\) 種取值,則整棵樹有 \(k*(k-1)^{n-1}\) 個取值,但是這樣計算出來可能用不完 \(k\) 個顏色。
於是設 \(F_k=k*(k-1)^{n-1}\) 表示最多用 \(k\) 個顏色的方案數,\(f_k\)
#include <cstdio> #include <algorithm> #include <cmath> #include <cstring> #define LL long long using namespace std; const int MAXN = 2505, Mod = 1e9 + 7; int n, k; LL jc[MAXN], inv[MAXN], ans; LL Qpow(LL x, int y) { LL ans = 1; for(; y; y >>= 1) { if(y & 1) ans = ans * x % Mod; x = x * x % Mod; } return ans; } LL C(int x, int y) { if(x < 0 || y < 0 || x < y) return 0; return jc[x] * inv[y] % Mod * inv[x - y] % Mod; } int main() { int x; scanf("%d%d", &n, &k); jc[0] = 1; for(int i = 1; i <= k; i ++) jc[i] = jc[i - 1] * i % Mod; inv[k] = Qpow(jc[k], Mod - 2); for(int i = k - 1; i >= 0; i --) inv[i] = inv[i + 1] * (i + 1) % Mod; for(int i = 2; i <= n; i ++) scanf("%d", &x); for(int i = 0; i <= k; i ++) ans = (ans + Qpow(Mod - 1, k - i) * C(k, i) % Mod * i % Mod * Qpow(i - 1, n - 1)) % Mod; printf("%lld", ans); return 0; }