2025牛客暑期多校第4场——G
考虑一个序列最中间的左括号和右括号,如果这两个交换那么序列是不合法的,由此可以猜测确定操作序列唯一确定的条件。利用一种抽象的前缀和,把左括号看成 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;
}