BZOJ1996 [Hnoi2010] 合唱队
Description
Input
Output
Sample Input
4
1701 1702 1703 1704
1701 1702 1703 1704
Sample Output
8
HINT
Solution
令$f_{i,j}$表示区间$[j,i+j]$在限定最后一个放$i$的情况下的方案数(之所以不是$[j,i]$,是因为那样不好滚动),$g_{i,j}$是限定最后一个放$i+j$的方案数。
转移时考虑上次放的是哪一个就可以了。要特殊处理$i=1$的情况。
代码:
#include <algorithm> #include <cstdio> const int N = 1005; const int mod = 19650827; int H[N], _f[2][N], _g[2][N]; int main() { int n; scanf("%d", &n); for (int i = 0; i < n; ++i) scanf("%d", &H[i]); int *f = _f[0], *g = _g[0], *ff = _f[1], *gg = _g[1]; for (int i = 0; i < n; ++i) f[i] = 1; for (int i = 1; i < n; ++i) { std::swap(f, ff); std::swap(g, gg); for (int j = 0; i + j < n; ++j) { f[j] = g[j] = 0; if (H[j] < H[j + 1]) f[j] += ff[j + 1]; if (H[j] < H[j + i]) f[j] += gg[j + 1]; if (H[j + i] > H[j]) g[j] += ff[j]; if (H[j + i] > H[j + i - 1]) g[j] += gg[j]; f[j] %= mod; g[j] %= mod; //printf("%d %d ", f[j], g[j]); } //printf("\n"); } printf("%d\n", (f[0] + g[0]) % mod); return 0; }