UVALive 7143 Room Assignment(组合数学+DP)(2014 Asia Shanghai Regional Contest)
題目鏈接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=648&page=show_problem&problem=5155
There are N guests checking in at the front desk of the hotel. 2K (0 ≤ 2K ≤ N) of them are twins.
There are M rooms available. Each room has capacity ci which means how many guests it can hold.
It happens that the total room capacity is N, i.e. c1 + c2 + . . . + cM = N.
The hotel receptionist wonders how many different room assignments to accommodate all guests.
Since the, receptionist cannot tell the two twins in any pair of twins apart, two room assignments are
considered the same if one can be generated from the other by swapping the two twins in each of some
number of pairs. For rooms with capacity greater than 1, it only matters which people are in the room;
they are not considered to be in any particular order within the room.
Input
The first line of the input gives the number of test cases, T. T test cases follow. Each test case starts
with three integers N, M, and K, which indicates the number of guests, the number of rooms, and the
number of pairs of twins. The following line contains M integers, c1, c2, …, cM, which indicates the i-th
room’s capacity.
Output
For each test case, first output one line containing ‘Case #x: y’, where x is the test case number
(starting from 1) and y is the number of different room assignments modulo 1,000,000,007 (109 + 7).
?
題目大意:有n個顏色的球,其中有k對球顏色相同,別的都是完全不同的。給m個盒子,每個盒子的容量為c[i],有sum{c[i]}=n。問:有多少種姿勢可以把n個球全部放入盒子中。
思路:首先這是一條組合計數的動態規劃。
用dp[i][r]表示,前i個盒子已經放完了,手上還拿著r對同色球。
設對于狀態dp[i][r],在第 i+1 個盒子中,我們要從 r 對同色球中取出 a 對,拿其中一個放入盒子 i+1 ;從剩下的 r-a 對同色球中,拿出 b 對,全部放入盒子 i+1 中;再從其他剩下的未放入盒子的球里面(假設有 sum 個),取 c[i]-a-2*b 個放入睇 i+1 個盒子中。這樣便轉移到了狀態dp[i+1][r-a-b]。
狀態轉移方程為:dp[i+1][r-a-b] = dp[i][r] * comb(r, a) * comb(r - a, b) * comb(sum - 2 * r, c[i] - a - 2 * b).
其中comb(p, q)表示從 p 個物體中選出 q 個的組合數。
至于在同色球中只選出其中一個球的問題,可以考慮:給兩個球強行編號為1、2,然后強行要求1必需放在2的前面,這樣就不會產生重復。當我們放入球1之后,球2就與其他普通的球無異了,無需任何處理。
然后預處理一下階乘及其逆元,利用公式comb(p, q) = p! / q! / (p-q)!,在O(1)時間內求出組合數。
總的時間復雜度為O(mk^3)。
?
代碼(1.252S):
1 #include <cstdio> 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 using namespace std; 6 typedef long long LL; 7 8 const int MAXN = 100010; 9 const int MOD = 1e9 + 7; 10 11 int inv[MAXN], fact[MAXN]; 12 13 int _inv(int x) { 14 if(x == 1) return 1; 15 return LL(MOD - MOD / x) * _inv(MOD % x) % MOD; 16 } 17 18 void init(int n = 100000) { 19 fact[0] = 1; 20 for(int i = 1; i <= n; ++i) 21 fact[i] = fact[i - 1] * LL(i) % MOD; 22 for(int i = 0; i <= n; ++i) 23 inv[i] = _inv(fact[i]); 24 } 25 26 LL comb(int a, int b) { 27 if(a < b) return 0; 28 return LL(fact[a]) * inv[b] % MOD * LL(inv[a - b]) % MOD; 29 } 30 31 int dp[13][111]; 32 int c[13]; 33 int T, n, m, k; 34 35 int mulmul(LL a, LL b, LL c, LL d) { 36 return a * b % MOD * c % MOD * d % MOD; 37 } 38 39 void update_add(int &a, int b) { 40 a += b; 41 if(a >= MOD) a -= MOD; 42 } 43 44 int solve() { 45 memset(dp, 0, sizeof(dp)); 46 dp[0][k] = 1; 47 for(int i = 0, sum = n; i < m; ++i) { 48 for(int r = 0; r <= k; ++r) if(dp[i][r]) { 49 if(sum < 2 * r) break; 50 for(int a = 0; a <= r; ++a) { 51 for(int b = 0; b + a <= r; ++b) { 52 if(c[i + 1] - a - 2 * b < 0) break; 53 int t = mulmul(dp[i][r], comb(r, a), comb(r - a, b), comb(sum - 2 * r, c[i + 1] - a - 2 * b)); 54 update_add(dp[i + 1][r - a - b], t); 55 } 56 if(i == m - 1) break; /// if i = m - 1 then a must be zero 57 } 58 } 59 sum -= c[i + 1]; 60 } 61 return dp[m][0]; 62 } 63 64 int main() { 65 init(); 66 //printf("%d\n", comb(10, 1)); 67 scanf("%d", &T); 68 for(int t = 1; t <= T; ++t) { 69 scanf("%d%d%d", &n, &m, &k); 70 for(int i = 1; i <= m; ++i) scanf("%d", &c[i]); 71 printf("Case #%d: %d\n", t, solve()); 72 } 73 } View Code?
轉載于:https://www.cnblogs.com/oyking/p/4508260.html
總結
以上是生活随笔為你收集整理的UVALive 7143 Room Assignment(组合数学+DP)(2014 Asia Shanghai Regional Contest)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: fastweixin v1.3.0 发布
- 下一篇: 【一个iOS官方文档错误】关于keyWi