# UVALive 7143 Room Assignment（组合数学+DP）（2014 Asia Shanghai Regional Contest）

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).

 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

posted @ 2015-05-16 17:54  Oyking  阅读(967)  评论(0编辑  收藏