Solution - CF909C
Solution.
很显然的一道 DP 。
定义状态 \(dp_{i,j}\) 为在第 \(i\) 行有 \(j\) 个换行的方案数。
假设第 \(i-1\) 行为 \(\texttt{f}\) ,那么第 \(i\) 行就必须多一个换行,所以 \(dp_{i,j}=dp_{i-1,j-1}\)
否则第 \(i-1\) 行为 \(\texttt{s}\) ,此时不难推出第 \(i\) 行换行个数的范围是 \(j\sim i-2\) ,则 \(dp_{i,j}=\sum\limits_{k=j}^{i-2}dp_{i-1,k}\) 。
此时时间复杂度为 \(\mathcal O(n^3)\) ,还不够优秀。
我们可以注意到 \(\sum\limits_{k=j}^{i-2}dp_{i-1,k}\) 可以用前缀和来维护。这样复杂度就降为 \(\mathcal O(n^2)\) 。
Code.
#include <bits/stdc++.h>
#define int long long
using namespace std;
template <typename T>
void read(T &x) {
x = 0; T f = 1;
char c;
c = getchar();
while (c < '0' || c > '9') {
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') {
x = (x << 1) + (x << 3) + c - '0';
c = getchar();
}
x *= f;
}
const int MOD = 1e9 + 7;
char a[5005];
int dp[5005][5005];
int sum[5005];
int n;
signed main() {
read(n);
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
dp[1][0] = 1;
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= i; j++) {
if (a[i - 1] == 'f') dp[i][j] = dp[i - 1][j - 1] % MOD;
else {
dp[i][j] = (dp[i][j] + sum[i - 2] - sum[j - 1] + MOD) % MOD;
}
}
for (int j = 0; j <= i; j++) {
sum[j] = (sum[j - 1] + dp[i][j]) % MOD;
}
}
int ans = 0;
for (int i = 0; i <= n; i++) {
ans = (ans + dp[n][i]) % MOD;
}
printf("%lld", ans);
return 0;
}
本文来自博客园,作者:cqbzjyh,转载请注明原文链接:https://www.cnblogs.com/cqbzjyh/p/15998118.html