Loading

洛谷 P8003 题解

Hard Brackets Inserting - 洛谷

提交率 1.13k 但是通过人数 22 最可怕的是还是道蓝题

这个题的通过率比较离谱,不过也可以理解,因为这道题的性质有点容易想错,即使非常接近也过不了这道题。

我们通过简单的手摸可以发现简单的规律,我们发现我们填进去的括号首先一定不能够形成新的括号,并且左括号和右括号是相对独立的,我们只能把左括号加入进最右边的一段左括号中或者是末尾,但是要注意,插入到最右边的一段左括号中依然有限制,那就是这最右边的一段左括号不能被其它括号对所包含,右括号同理。

注意关于 \(n=2\) 的特判,\(n=2\) 的时候随便插入,没有上面不能组成统一括号对的限制。
处理出来直接统计即可。

代码:

#include<bits/stdc++.h>
#define dd double
#define ld long double
#define ll long long
#define uint unsigned int
#define ull unsigned long long
#define N 1000100
#define M number
using namespace std;

const int INF=0x3f3f3f3f;
const int mod=998244353;

template<typename T> inline void read(T &x) {
    x=0; int f=1;
    char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c == '-') f=-f;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    x*=f;
}

int n,m,t,f[N],g[N],Jie[N],Inv[N],Jieinv[N],Ans;
const int lim=1000000;
char s[N];

inline int C(int n,int m){
    if(n<m) return 0;
    return 1ll*Jie[n]*Jieinv[m]%mod*Jieinv[n-m]%mod;
}

inline int ksm(int a,int b,int mod){int res=1;while(b){if(b&1){res=1ll*res*a%mod;}a=1ll*a*a%mod;b>>=1;}return res;}

int main(){
    // freopen("my.in","r",stdin);
    // freopen("my.out","w",stdout);
    read(t);
    Jie[0]=1;for(int i=1;i<=lim;i++) Jie[i]=1ll*Jie[i-1]*i%mod;
    Inv[1]=1;for(int i=2;i<=lim;i++) Inv[i]=1ll*(mod-mod/i)*Inv[mod%i]%mod;
    Jieinv[0]=1;for(int i=1;i<=lim;i++) Jieinv[i]=1ll*Jieinv[i-1]*Inv[i]%mod;
    while(t--){
        // printf("here\n");
        read(n);read(m);
        scanf("%s",s+1);
        if(n==2){
            printf("%d\n",1ll*ksm(2,m-n,mod)*m%mod*(m-1)%mod*ksm(2,mod-2,mod)%mod);continue;
        }
        int cnt1=0,cnt2=0;
        for(int i=n;i>=1;i--){
            if(s[i]=='(') cnt1++;
            if(s[i]==')'){
                if(cnt1){cnt1=cnt2=-INF;break;}
                cnt2++;
            }
            if(cnt1==cnt2) break;
        }
        // printf("%d %d\n",cnt1,cnt2);
        if(cnt1==-INF){
            for(int i=0;i<=m-n;i++) f[i]=1;
        }
        else{
            for(int i=0;i<=m-n;i++) f[i]=C(cnt1+i,i);
            for(int i=1;i<=m-n;i++) f[i]=(f[i]+f[i-1])%mod;
        }
        // for(int i=0;i<=m-n;i++) printf("%d ",f[i]);puts("");
        cnt1=cnt2=0;
        for(int i=1;i<=n;i++){
            if(s[i]=='('){
                if(cnt2){cnt1=cnt2=-INF;break;}
                cnt1++;
            }
            if(s[i]==')') cnt2++;
            if(cnt1==cnt2) break;
        }
        // printf("%d %d\n",cnt1,cnt2);
        if(cnt2==-INF){
            for(int i=0;i<=m-n;i++) g[i]=1;
        }
        else{
            for(int i=0;i<=m-n;i++) g[i]=C(cnt2+i,i);
            for(int i=1;i<=m-n;i++) g[i]=(g[i-1]+g[i])%mod;
        }
        // for(int i=0;i<=m-n;i++) printf("%d ",g[i]);puts("");
        for(int i=0;i<=m-n;i++) Ans=(Ans+1ll*f[i]*g[m-n-i]%mod)%mod;
        printf("%d\n",Ans);Ans=0;
        for(int i=0;i<=m-n;i++) f[i]=g[i]=0;
    }
    return 0;
}
posted @ 2022-01-07 21:21  hyl天梦  阅读(107)  评论(0编辑  收藏  举报