Lesson Timetable
题目链接:https://www.codeforces.com/contest/37/problem/D
数据范围:略。
题解:
根本就没想到可以动态规划。
首先从前往后处理,仔细一想是有道理的。
因为如果处理到了$i$,那么前面的所有值都是可以对当前值有贡献的。
即,我们设状态$dp_{i, j}$表示前$i$个教室有$j$个人(第二节课)的方案数。
最后用阶乘即可。
代码:
#include <bits/stdc++.h> #define setIO(s) freopen(s".in", "r", stdin), freopen(s".out", "w", stdout) #define N 1010 using namespace std; typedef long long ll; const int mod = 1000000007; char *p1, *p2, buf[100000]; #define nc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1 ++ ) int rd() { int x = 0; char c = nc(); while (c < 48) { c = nc(); } while (c > 47) { x = (((x << 2) + x) << 1) + (c ^ 48), c = nc(); } return x; } int fac[N], inv[N]; int qpow(int x, int y) { int ans = 1; while (y) { if (y & 1) { ans = (ll)ans * x % mod; } y >>= 1; x = (ll)x * x % mod; } return ans; } void init() { fac[0] = 1; inv[0] = 1; for (int i = 1; i < N; i ++ ) { fac[i] = (ll)fac[i - 1] * i % mod; inv[i] = qpow(fac[i], mod - 2); } } int dp[1010][1010], bfr[1010], x[1010], y[1010]; int C(int x, int y) { return (ll)fac[x] * inv[y] % mod * inv[x - y] % mod; } int main() { setIO("num"); init(); int m = rd(); for (int i = 1; i <= m; i ++ ) { x[i] = rd(), bfr[i] = bfr[i - 1] + x[i]; } for (int i = 1; i <= m; i ++ ) { y[i] = rd(); } dp[0][0] = 1; for (int i = 1; i <= m; i ++ ) { for (int j = 0; j <= bfr[i]; j ++ ) { for (int k = 0; k <= min(j, y[i]); k ++ ) { (dp[i][j] += (ll)dp[i - 1][j - k] * C(bfr[i] - (j - k), k) % mod) %= mod; } } } // cout << dp[m][bfr[m]] << endl ; int ans = (ll)dp[m][bfr[m]] * fac[bfr[m]] % mod; for (int i = 1; i <= m; i ++ ) { ans = (ll)ans * inv[x[i]]; } cout << ans << endl ; return 0; }