题目大意
1. 核心定义
2. 任务要求
给定一个长度为 n (1≤n≤100) 的括号序列 s,求 s 的所有非空子序列的得分之和,结果对 998244353 取模。
3. 样例解释
思路讲解
首先,D1 当中,我们发现一个规律,就是只要 s 串只要是有答案的,其答案就是 ∣s∣−2,那么其有答案的条件是第一个 ) 出现的位置后,又至少出现了出现了两个 (。
我们可以定义一个如下状态:

⚠️注意:这里的长度,个数,指的是合法方案个数及其合法方案的总(后缀)长度,这样子定义是为了方便记忆化搜索。
总体上的记忆化搜索过程可以描述为这样:
res←(0,0)if unbalance=0∧state=3:res←(1,1)lres←dfs(idx,unbalance,state)if idx=0:lreslen←lreslen+lresnumres←res+lres
那么之所以不在 idx=0 的时候进行这个操作,是因为 0 是虚拟节点,没有实际字符。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| auto dfs=[&](auto && self,int idx,int unbalance,int state) -> Len_num{ if (unbalance<0) { return {0,0}; } if (vis[idx][unbalance][state]) { return dp[idx][unbalance][state]; } vis[idx][unbalance][state]=true; Len_num res={0,0}; if (unbalance==0 && state==3) { res={1,1}; } for (int i=idx+1;i<=N;++i) { Len_num lres; if (s[i]==')') { lres=self(self,i,unbalance-1,max(1,state)); }else { int to_state; if (state==0) to_state=0; else to_state=min(3,state+1); lres=self(self,i,unbalance+1,to_state); } res+=lres; if (lres.len!=0 && idx!=0) { res.len+=lres.num; } res%=mod; } dp[idx][unbalance][state]=res; return res; }; Len_num res=dfs(dfs,0,0,0);
|
AC代码
AC
https://codeforces.com/contest/2191/submission/358546432
源代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
|
#include <bits/stdc++.h> #include <ranges> #define all(vec) vec.begin(),vec.end() #define lson(o) (o<<1) #define rson(o) (o<<1|1) #define SZ(a) ((long long) a.size()) #define debug(var) cerr << #var <<":"<<var<<"\n"; #define cend cerr<<"\n-----------\n" #define fsp(x) fixed<<setprecision(x)
using namespace std;
using ll = long long; using ull = unsigned long long; using DB = double; using LD = long double;
using CD = complex<double>;
static constexpr ll MAXN = (ll)1e6+10, INF = (1ll<<61)-1; static constexpr ll mod = 998244353; static constexpr double eps = 1e-8; const double pi = acos(-1.0);
ll lT;
struct Len_num { ll len,num; void operator+=(const Len_num &o) { len+=o.len; num+=o.num; } void operator%=(const ll a) { len%=a; num%=a; } }; void Solve() { ll N; cin >> N; string s; cin>>s; s.insert(s.begin(),'#'); vector dp(N+2,vector(N+2,vector<Len_num>(4))); vector vis(N+2,vector(N+2,vector<char>(4))); auto dfs=[&](auto && self,int idx,int unbalance,int state) -> Len_num{ if (unbalance<0) { return {0,0}; } if (vis[idx][unbalance][state]) { return dp[idx][unbalance][state]; } vis[idx][unbalance][state]=true; Len_num res={0,0}; if (unbalance==0 && state==3) { res={1,1}; } for (int i=idx+1;i<=N;++i) { Len_num lres; if (s[i]==')') { lres=self(self,i,unbalance-1,max(1,state)); }else { int to_state; if (state==0) to_state=0; else to_state=min(3,state+1); lres=self(self,i,unbalance+1,to_state); } res+=lres; if (lres.len!=0 && idx!=0) { res.len+=lres.num; } res%=mod; } dp[idx][unbalance][state]=res; return res; }; Len_num res=dfs(dfs,0,0,0); ll ans=res.len-res.num*2; ans%=mod; if (ans<0) { ans+=mod; } cout<<ans<<"\n"; }
signed main() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); cin >> lT; while(lT--) Solve(); return 0; }
|
心路历程(WA,TLE,MLE……)
res←{0,0}unbalance=0 and state=3:res←{1,1}lres←dfs(idx,unbalance,state)idx=0:lres.len←lres.len+lres.numres←res+lres