Luo's oj P1916 簡單的序列(bracket)

傳送門

分析

我們將左括號看作 1,右括號看作 -1,則一個合法的括號序列需要滿足:
*所有括號的總和爲 0
*每個前綴和均不小於0
我們先統計出串 s 的總和 a 以及最小的前綴和 b,然後枚舉串 p 的長度 i 以及總和 j, 考慮到需要滿足第二個條件,那麼 j 需要滿足 j+b>=0。記 f[ i ][ j ] 爲長度爲 i ,總和爲 j 的括號序列數量,此時 p 的方案數爲 f[ i ][ j ]q 的方案數爲 f[ n - m - i ][ j + a ],將它們的乘積計入答案即可。
f 可以通過一個簡單的 DP 求出,時空複雜度均爲 O((n-m)^2)

#include<bits/stdc++.h>
#define ll long long
#define N 100005
#define M 2005
#define mod 1000000007
using namespace std;
int n,m,k,u,ans,f[M][M];
char s[N];
int main(){
    scanf("%d%d",&n,&m);
    scanf("%s",s+1);
    for(int i=1;i<=m;i++){
        u+=s[i]=='(' ? 1:-1;
        k=min(k,u);
    }
    f[0][0]=1;
    for(int i=1;i<=n-m;i++)
        for(int j=0;j<=i;j++){
            f[i][j]=0;
            if(j>0)f[i][j]=(f[i][j]+f[i-1][j-1])%mod;
            if(j<i-1)f[i][j]=(f[i][j]+f[i-1][j+1])%mod;
        }
    for(int i=-k;i<=n-m;i++)
        for(int j=-k;j<=i;j++)
            if(u+j<=n-m-i) ans=(ans+(ll)f[i][j]*f[n-m-i][u+j])%mod;
    printf("%d",ans);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章