给定n个0和n个1,它们将按照某种顺序排成长度为2n的序列,求它们能排列成的所有序列中,能够满足任意前缀序列中0的个数都不少于1的个数的序列有多少个。
输出的答案对1e9+7取模。
输入格式
共一行,包含整数n。
输出格式
共一行,包含一个整数,表示答案。
数据范围
1≤n≤1e5
输入样例:
3
输出样例:
5
分析:
这道题题意较为容易理解,计算满足任意前缀0的次数不小于1的序列个数,将这个问题转化为组合数问题就是在2n步骤中选择满足条件的n步来计算数量,那么总的序列个数就是
C
2
n
n
C_{2n}^{n}
C2nn。
再找出满足条件的序列次数,这里用到了卡特兰数
分析问题,以
n
=
6
n=6
n=6 为例,则总的方案数可以看作从(0,0)点到(6,6)的路径数,0为向右走,1为向上走。
满足条件的路径数为不经过红颜色边
任何经过红颜色边的路径,对红线的轴对称可以走到(5,7)这个点,反过来,任何到达(5,7)的路径都对应一条不满足条件(前缀序列中0的个数都不少于1的个数)的路径。
因此,这道题的结果就可以写成
(
C
2
n
n
−
C
2
n
n
−
1
)
%
m
o
d
=
C
2
n
n
n
+
1
%
m
o
d
(C_{2n}^{n}-C_{2n}^{n-1})\%mod=\frac{C_{2n}^{n}}{n+1}\%mod
(C2nn−C2nn−1)%mod=n+1C2nn%mod,除法运算可以用逆元来转化成乘法运算。
代码如下:
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
int qmi(int a,int b)
{
int res=1;
while(b)
{
if(b&1) res=(ll)res*a%mod;
a=(ll)a*a%mod;
b>>=1;
}
return res;
}
int C(int a,int b)
{
int res=1;
for(int i=a,j=1;j<=b;j++,i--)
{
res=(ll)res*i%mod*qmi(j,mod-2)%mod;
}
return res;
}
int main()
{
int n;
scanf("%d",&n);
printf("%d\n",(ll)C(2*n,n)*qmi(n+1,mod-2)%mod);
return 0;
}