Description
在长度为n的区间上放
Input
三个整数
Output
输出满足条件的括号序列个数,结果模109+7
Sample Input
1 1 1
Sample Output
1
Solution
先不考虑括号间的相对顺序,求出有顺序的括号序列个数再乘上n!即为答案,首先一个位置不可能出现两个相同的括号,这样必然会有一个区间包含另一个区间,故一个位置只有四种情况,左括号,右括号,左括号和右括号,不放括号;每个位置括号放好后,括号序列固定,因为最后一个右括号必然匹配最后一个左括号,否则最后一个左括号会匹配一个位置在最后一个右括号之前的右括号,那么就会出现包含,以此类推确定每对括号,故问题变成一个简单dp,令dp[i][j][k]表示前i个位置放
Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f,maxn=333;
#define mod 1000000007
int n,m,x,dp[2][maxn][maxn],fact[maxn];
void init(int n=330)
{
fact[0]=1;
for(int i=1;i<=n;i++)fact[i]=(ll)i*fact[i-1]%mod;
}
void add(int &x,int y)
{
x=x+y>=mod?x+y-mod:x+y;
}
int main()
{
//只要一个端点不出现两个及以上的左括号或右括号,那么n个左括号和n个右括号对应唯一的互不包含的区间
scanf("%d%d%d",&n,&m,&x);
init();
if(n>m)printf("0\n");
else
{
dp[0][0][0]=1;
int cur=0;
for(int i=1;i<=m;i++)
{
cur^=1;
for(int j=0;j<=n;j++)
for(int k=0;k<=j;k++)
{
dp[cur][j][k]=0;
if(j&&k)add(dp[cur][j][k],dp[cur^1][j-1][k-1]);//[]
if(j-1>=k)add(dp[cur][j][k],dp[cur^1][j-1][k]);//[
if(i!=x)
{
if(k)add(dp[cur][j][k],dp[cur^1][j][k-1]);//]
add(dp[cur][j][k],dp[cur^1][j][k]);//NULL
}
}
}
int ans=(ll)dp[cur][n][n]*fact[n]%mod;
printf("%d\n",ans);
}
return 0;
}