考虑一个序列最中间的左括号和右括号,如果这两个交换那么序列是不合法的,由此可以猜测确定操作序列唯一确定的条件。利用一种抽象的前缀和,把左括号看成 111 ,右括号看成 −1-1−1 ,对于一个左括号,如果和一个右括号中间的有一个前缀和是 <2<2<2 的,那么操作序列就可以唯一确定,每次枚举左括号位置,计算合法方案数求和即可.
为什么每个左括号都可以计算答案,因为一个合法序列的左括号都有一个右括号与之匹配
#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
using namespace std;
using i64 = long long;
using i128 = __int128;
constexpr int mod = 998244353;
constexpr int maxn = 1e6+10;
int pre[maxn];
i64 qp(i64 a,i64 b){
i64 ans = 1;
while(b){
if(b&1) ans = ans*a%mod;
b>>=1;
a = a*a%mod;
}
return ans;
}
void solve(){
string s;cin>>s;
for(int i = 0;i<s.size();++i){
pre[i+1] = pre[i]+(s[i]=='('?1:-1);
}
int n = s.size();
i64 ans = qp(2,n>>1);
int cntl=n/2, cntr = 1,cntrr=1;
for(int i = s.size()-2;i>=0;--i){
if(pre[i+1]<2){
cntr=cntrr;
}
if(s[i]=='(') cntl--;
else cntrr++;
if(s[i]=='('){
(ans+=qp(2,cntl+cntr))%=mod;
}
}
cout<<ans*qp(qp(2,n),mod-2)%mod<<"\n";
}
signed main(){
ios::sync_with_stdio(0);cin.tie(0);
int t=1;
//cin>>t;
while(t--) solve();
return 0;
}