1. 程式人生 > 其它 >洛谷 P8003 題解

洛谷 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;
}