天天看點

Codeforces Round #343 (Div. 2) C. Famil Door and Brackets(簡單dp)

題目連結:點這裡!!!!

題意:

給你一長度為m僅包含'('和')'的字元串s,叫你組成一個長度為n的字元串。

使得滿足下列兩個條件:

1、字元串中'('和')'的數量是相等的。

2、字元串字首中'('的數量大于等于')'。

問你p+s+q得到符合條件長度為n的字元串的(p,q)組合有多少種?答案對1e9+7取模。

資料範圍1<=m<=n<=100000,n-m<=2000

題解:

我設dp[i][j]為前i位中'('比')'多j個的方案數為多少。

轉移方程為:dp[i][j]=dp[i-1][j-1]+dp[i-1][j+1]。

然後我們去枚舉p符合條件組成方式,再判斷q是否可行,就ok了,具體看代碼吧。

代碼:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<sstream>
#include<algorithm>
#include<vector>
#include<bitset>
#include<set>
#include<queue>
#include<stack>
#include<map>
#include<cstdlib>
#include<cmath>
#define LL long long
#define pb push_back
#define pa pair<int,int>
#define clr(a,b) memset(a,b,sizeof(a))
#define lson lr<<1,l,mid
#define rson lr<<1|1,mid+1,r
#define bug(x) printf("%d++++++++++++++++++++%d\n",x,x)
#define key_value ch[ch[root][1]][0]
#pragma comment(linker, "/STACK:102400000000,102400000000")
const LL  MOD = 1000000007;
const int N = 2000+15;
const int maxn = 1e5+15;
const int letter = 130;
const LL INF = 1e7;
const double pi=acos(-1.0);
const double eps=1e-10;
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
LL dp[N][N];
char s[maxn];
int n,m;
int main(){
    scanf("%d%d",&n,&m);
    scanf("%s",s);
    dp[0][0]=1;
    for(int i=1;i<=n-m;i++){
        dp[i][0]=dp[i-1][1];
        for(int j=1;j<=i;j++){
            dp[i][j]=((dp[i-1][j-1]+dp[i-1][j+1])%MOD+MOD)%MOD;
        }
    }
    int ll=-1000000;
    int sum=0;
    for(int i=0;i<m;i++){
        if(s[i]==')') sum++;
        else sum--;
        ll=max(ll,sum);
    }
    sum=-sum;
    LL ans=0;
    for(int i=0;i<=n-m;i++)
    for(int j=0;j<=i;j++){
        if(j>=ll&&j+sum<=n-m-i){
            ans=(ans+dp[i][j]*dp[n-m-i][j+sum]%MOD)%MOD;
        }
    }
    printf("%I64d\n",ans);
    return 0;
}