题目大意:
长度为 n ( ≤ 2000 ) n(\le 2000) n(≤2000)的字符串,字符串包含 ′ ( ′ '(' ′(′, ′ ? ′ '?' ′?′, ′ ) ′ ')' ′)′, ′ ? ′ '?' ′?′可以是 ′ ( ′ '(' ′(′或者 ′ ) ′ ')' ′)′,对于一个不含 ′ ? ′ '?' ′?′的序列,计算其子序列的最大深度,询问不同方案下最大深度和。
解题思路:
- 设 p r e i , j pre_{i,j} prei,j为 1 ∼ i 1\sim i 1∼i的前缀字符,有 j j j个 ′ ( ′ '(' ′(′,这个可以用组合数来算,同理算 s u f i , j suf_{i,j} sufi,j
- a n s = ∑ i = 1 n ∑ j = 1 n p r e i , j ∗ s u f i + 1 , j ∗ j ans = \sum_{i=1}^n\sum_{j=1}^n pre_{i,j}*suf_{i+1,j}*j ans=∑i=1n∑j=1nprei,j∗sufi+1,j∗j
AC代码:
#include <bits/stdc++.h>
#define ft first
#define sd second
#define pb push_back
#define IOS ios::sync_with_stdio(false), cin.tie(0), cout.tie(0) //不能跟puts混用
#define seteps(N) fixed << setprecision(N)
#define endl "\n"
const int maxn = 2e3 + 10;
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int, int> pii;
const int mod = 998244353;
char s[maxn];
int n, psum0[maxn], psum1[maxn], ssum0[maxn], ssum1[maxn];
ll pre[maxn][maxn], suf[maxn][maxn], fac[maxn], rfac[maxn];
ll qpow(ll a, ll b, ll mod) {
ll res = 1;
while (b) {
if (b & 1) res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
}
void init() {
fac[0] = 1;
for (int i = 1; i < maxn; i++) fac[i] = fac[i - 1] * i % mod;
rfac[maxn - 1] = qpow(fac[maxn - 1], mod - 2, mod);
for (int i = maxn - 2; i >= 0; i--) rfac[i] = rfac[i + 1] * (i + 1) % mod;
}
ll C(ll n, ll m) {
if (n < m) return 0;
return fac[n] * rfac[n - m] % mod * rfac[m] % mod;
}
int main() {
IOS;
init();
cin >> s + 1;
n = strlen(s + 1);
for (int i = 1; i <= n; i++) psum0[i] = psum0[i - 1] + (s[i] == '?');
for (int i = 1; i <= n; i++) psum1[i] = psum1[i - 1] + (s[i] == '(');
for (int i = n; i >= 1; i--) ssum0[i] = ssum0[i + 1] + (s[i] == '?');
for (int i = n; i >= 1; i--) ssum1[i] = ssum1[i + 1] + (s[i] == ')');
for (int i = 1; i <= n; i++)
for (int j = psum1[i]; j <= psum0[i] + psum1[i]; j++) {
pre[i][j] = C(psum0[i], j - psum1[i]);
}
for (int i = 1; i <= n; i++)
for (int j = ssum1[i]; j <= ssum0[i] + ssum1[i]; j++) {
suf[i][j] = C(ssum0[i], j - ssum1[i]);
}
ll ans = 0;
for (int i = 1; i <= n - 1; i++)
for (int j = 1; j <= n; j++)
ans = (ans + pre[i][j] * suf[i + 1][j] % mod * j % mod) % mod;
cout << ans << endl;
}