2025牛客暑期多校第4场——G

在这里插入图片描述

考虑一个序列最中间的左括号和右括号,如果这两个交换那么序列是不合法的,由此可以猜测确定操作序列唯一确定的条件。利用一种抽象的前缀和,把左括号看成 111 ,右括号看成 −1-11 ,对于一个左括号,如果和一个右括号中间的有一个前缀和是 <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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值