CF1264D1 Beautiful Bracket Sequence (easy version)

考虑在一个确定的括号序列中,我们可以枚举中间位置,按左右最长延伸出去的答案计算。

我们很自然的思考,我们直接维护左右两边,在删除一些字符后能够延伸的最长长度。

我们设\(f_{i,j}\)\(i\)点合法删除向左延伸的最大长度。

\( f_{i,j} = \left\{ \begin{aligned} &f_{i - 1,j} (a[i] = ')'\ )\\ &f_{i - 1,j - 1}(a[i] = ')'\ )\\ &f_{i - 1,j} + f_{i - 1 ,j - 1} (a[i] = '?'\ )\\ \end{aligned} \right. \)

\(g_{i,j}\)为向右延伸,则有同样的转移。

\(ans = \sum_{i = 1}^n\sum_{j = 1}^j f_{i,j} * g_{i + 1,j} * j\)

#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long 
#define N 2005
#define mod 998244353

char a[N];

ll n;
ll f[N][N],g[N][N];

int main(){
	scanf("%s",a + 1);
	n = strlen(a + 1);
	f[0][0] = 1;
	for(int i = 1;i <= n;++i){
		if(a[i] == '(' || a[i] == '?')
		for(int j = 1;j <= n;++j)
		f[i][j] = (f[i][j] + f[i - 1][j - 1]) % mod;
		if(a[i] == ')' || a[i] == '?')
		for(int j = 0;j <= n;++j)
		f[i][j] = (f[i][j] + f[i - 1][j]) % mod;		
	}
	g[n + 1][0] = 1;
	for(int i = n;i >= 1;--i){
		if(a[i] == ')' || a[i] == '?')
		for(int j = 1;j <= n;++j)
		g[i][j] = (g[i][j] + g[i + 1][j - 1]) % mod;
		if(a[i] == '(' || a[i] == '?')
		for(int j = 0;j <= n;++j)
		g[i][j] = (g[i][j] + g[i + 1][j]) % mod;
	}	
	ll ans = 0;
	for(int i = 1;i <= n - 1;++i)
	for(int j = 1;j <= n;++j)
	ans = (ans + f[i][j] * g[i + 1][j] % mod * j % mod) % mod;
	std::cout<<ans<<std::endl;
}
posted @ 2021-08-19 09:01  fhq_treap  阅读(46)  评论(0编辑  收藏  举报