Loading

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;
}
posted @ 2022-03-12 19:18  cqbzjyh  阅读(48)  评论(0编辑  收藏  举报