合法括号序列

题目描述

合法括号序列 键盘上有左括号(,右括号),和退格键-,共三个键。 牛牛希望按键n次,使得输入的字符串恰好一个合法的括号序列。 每按一次左括号(,字符串末尾追加一个左括号( 每按一次右括号),字符串末尾追加一个右括号) 每按一次退格键-,会删掉字符串的最后一个字符, 特别的,如果字符串为空,牛牛也可以按退格,但是什么都不会发生。 输出方案数对p取模,注意p可能不是质数。 注:只要按键方法不同,就是不同的方案,即使得到的序列一样。

输入描述:

输入一行两个整数n, p

输出描述:

输出一行一个整数表示答案。

示例1

输入

2 4

输出

0

说明

答案是4,有以下4个合法的序列()(-)—

备注:

对于所有数据: 2 <= n <= 1000, 2 <= p <= 1000030分: n <= 4070分: n <= 100
这里写图片描述

#include<bits/stdc++.h>
using namespace std;
inline int rd()
{
    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<<3)+(x<<1)+(ch^48);
        ch=getchar();
    }
    return x*f;
}
long long n,mod,dp[2005][2005],c[2005];
int main()
{
    c[0]=c[1]=1;
    cin>>n>>mod;
    for(int i=2;i<=n;i++)
    {
        for(int j=1;j<=i;j++)
        {
            c[i]=(c[i]+c[j-1]*c[i-j])%mod;
        }
    }
    dp[0][0]=1;
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=i;j++)
        {
            dp[i][j]=(dp[i-1][max(j-1,0)]+2*dp[i-1][j+1])%mod;
        }
    }
    long long ans=0;
    for(int i=0;2*i<=n;i++)
    {
        ans=(ans+dp[n][i*2]*c[i])%mod;
    }
    cout<<ans;
    return 0;
}

来源:nkw

猜你喜欢

转载自blog.csdn.net/qq_42500298/article/details/82729008