BZOJ3193: [JLOI2013]地形生成
阿新 • • 發佈:2018-12-23
turn return else sum pre ans 會有 bits names
傳送門
Sol
第一問可以考慮按照山的高度從大到小放
但是這樣如果遇到高度相同的就不好考慮,那麽同時要求數量限制從小到大
這樣每次放的時候後面的一定不會影響前面,並且高度相同的時候前面能放的位置後面的也能放
直接乘起來就好了
對於第二問,此時高度相同的會有影響
對於高度相同的一段,強制要求數量限制從小到大,並且後面的位置必須小於前面
設 \(f_{i,j}\) 表示放了 \(i\) 個到 \(j\) 個空位,最後一個放的在最後,的方案數
那麽 \(f_{i,j}=\sum_{k\le j}f_{i-1,k}\)
前綴和優化即可,最後把答案乘起來
# include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn(1005); const int mod(2011); struct Hill { int h, c; inline bool operator < (Hill b) const { return (h ^ b.h) ? h > b.h : c < b.c; } } h[maxn]; int n, f[maxn][maxn]; inline int Solve(int l, int r) { register int i, j, len = r - l + 1; for (i = 0; i <= len; ++i) for (j = 0; j <= l; ++j) f[i][j] = 0; for (i = 1; i <= l; ++i) f[0][i] = 1; for (i = 1; i <= len; ++i) { for (j = 1; j <= min(l, h[i + l - 1].c); ++j) f[i][j] = f[i - 1][j]; for (j = 1; j <= l; ++j) f[i][j] = (f[i][j] + f[i][j - 1]) % mod; } return f[len][l]; } int main() { register int i, c, ans; scanf("%d", &n); for (i = 1; i <= n; ++i) scanf("%d%d", &h[i].h, &h[i].c); sort(h + 1, h + n + 1); for (ans = 1, i = 2, c = 0; i <= n; ++i) { c = h[i].h == h[i - 1].h ? c + 1 : 0; ans = ans * min(i, h[i].c + c) % mod; } printf("%d ", ans); for (ans = 1, i = 1, c = 0; i <= n; ++i) if (i == n || h[i].h != h[i + 1].h) ans = ans * Solve(i - c, i) % mod, c = 0; else ++c; printf("%d\n", ans); return 0; }
BZOJ3193: [JLOI2013]地形生成