因为不能包含,所以一定没有相同的区间,我们可以先不考虑顺序,求出可能的方案数,然后乘上n!就是答案。
我们考虑按1~m的顺序枚举每一个数,由于不能包含,所以一个数上最多一个左区间和最多一个右区间,我们直接枚举这4种情况即可。因此
f[i][j][k]
f
[
i
]
[
j
]
[
k
]
,表示考虑前i个数,有j个左括号,k个右括号的方案数。
在dp到X的时候强行选左括号即可。
由于
nm<=1e5
n
m
<=
1
e
5
,当
n>m
n
>
m
时显然无解,因此
n<=1e5−−−√
n
<=
1
e
5
O(mn2)
O
(
m
n
2
)
可过。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 100010
#define mod 1000000007
inline char gc(){
static char buf[1<<16],*S,*T;
if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=gc();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
return x*f;
}
int n,m,X,f[2][500][500];//f[i][j][k],考虑前i个数,有j个左括号,k个右括号。
inline void inc(int &x,int y){x+=y;if(x>=mod) x-=mod;}
int main(){
// freopen("a.in","r",stdin);
n=read();m=read();X=read();
if(n>m){puts("0");return 0;}
int p=0;f[0][0][0]=1;
for(int i=1;i<=m;++i){
p;
for(int j=0;j<=n;++j)
for(int k=0;k<=j;++k){
if(!f[p][j][k]) continue;
if(i!=X) inc(f[p^1][j][k],f[p][j][k]);
if(j+1<=n) inc(f[p^1][j+1][k],f[p][j][k]);
if(k+1<=n&&i!=X) inc(f[p^1][j][k+1],f[p][j][k]);
if(k+1<=n&&j+1<=n) inc(f[p^1][j+1][k+1],f[p][j][k]);f[p][j][k]=0;
}p^=1;
}int ans=f[p][n][n];
for(int i=2;i<=n;++i) ans=(ll)ans*i%mod;
printf("%d\n",ans);
return 0;
}