【組合數學 容斥原理】ICPC2014西安 F. Color
阿新 • • 發佈:2018-11-06
https://vjudge.net/contest/265252#problem/F
給你n朵花,m種顏色,k (1 ≤ n, m ≤ 10^9 , 1 ≤ k ≤ 10^6 , k ≤ n, m)
花是一排,要求相鄰花染色不能相同,染色數量剛好等於k,問你染色的方案數
如果用<=k種顏色,那麼有k*(k-1)^(n-1) *C(k,1) 種方案 ——A
如果用<=k-1種顏色,那麼有(k-1)*(k-2)^(n-1) *C(k,2) 種方案 ——B
如果用<=k-2種顏色,那麼有(k-2)*(k-3)^(n-1) *C(k,3) 種方案 ——C
……
A方案包括了用k-1種顏色的要減去B,B中又包括了用k-2種顏色的要加上C
容斥原理!!!!
記得每一次要乘上C(k,i),因為減掉哪種顏色不確定
最後因為在m種顏色裡選k種,*C(m,k)
又因為m<=1e^9,但是k<=1e^7,
所以用遞推
記得容斥原理做的時候,減時先+mod,不然會出負的
#include <bits/stdc++.h> #define ll long long using namespace std; const ll mod = 1e9+7; ll fac[1000005], inv[1000005]; ll quickpow(ll a, ll b) { ll ret = 1; while(b) { if(b & 1) ret = (ret * a) % mod; a = (a * a) % mod; b >>= 1; } return ret; } void init(int p) { fac[0] = 1; for(int i = 1; i <= p; i++) fac[i]=(fac[i - 1] * i) % mod; inv[p] = quickpow(fac[p], mod - 2); for(int i = p - 1; i >= 0; i--) inv[i] = (inv[i + 1] * (i + 1)) % mod; } ll C(ll n, ll m) { return fac[n] * inv[m] % mod * inv[n - m] % mod; } int main() { int T, cas = 0; scanf("%d", &T); init(1000003); while(T --) { ll n, m, k; scanf("%lld%lld%lld", &n, &m, &k); ll ans = quickpow(k - 1, n - 1) * k % mod; for(int i = 1; i < k - 1; i++) { ll sum = quickpow(k - i - 1, n - 1) * (k - i) %mod * C(k , i) % mod; if(i & 1) ans = (ans - sum + mod) % mod; else ans = (ans + sum) % mod; } for(int i = m - k + 1; i <= m; i++) { ans = ans * i % mod; } ans = ans * inv[k] % mod; printf("Case #%d: %lld\n", ++cas, ans); } return 0; }