①. 题目
②. 思路
-
直接将问题转化为走格子,若 0 表示向右走,1 表示向上走,那么任何前缀中 0 的个数不少于 1 的个数就转化为,路径上的任意一点,横坐标大于等于纵坐标。所有前缀中0的个数大于1的个数都在红线以下,把经过红线的路径进行对称,那么他们的终点都会被映射到(n−1,n+1),只要计算终点是(n−1,n+1)的路径有多少个,再用总数减去就是最终的答案。
-
表示从 (0,0) 走到 (n,n) 的路径,在绿线及以下表示合法,若触碰红线即不合法。
-
算法核心:每一条从(0,0)走到(n,n)的非法路径都对应一条从(0,0)走到(n-1,n+1)的非法路径
-
直接推出公式 Cn2n−Cn−12n ,化简得 Cn2n/(n+1)
③. 学习点
组合计数_卡特兰数
④. 代码实现
import java.util.Scanner;
public class Main {
static int m=(int)1e9+7;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n=sc.nextInt();
long res=1;
//直接套用推出来的公式
for (int i = 1,j=2*n; i <=n; i++,j--) {
res=res*j%m; //求2n*(2n-1)*(2n-2)*...*(2n-n+1)
res=res*qmi(i,m-2,m)%m; //快速幂求n的阶乘的逆元
}
System.out.println(res*qmi(n+1,m-2,m)%m); //最后乘上n+1的逆元
}
//快速幂求 a^k%m
static long qmi(long a,long k,long m) {
long res=1;
while(k!=0) {
if((k&1)==1) res=res*a%m;
a=a*a%m;
k>>=1;
}
return res;
}
}