【数学】卡特兰数

卡特兰数

卡特兰数是一个数列,其前几项为(从第零项开始) :
1 , 1 , 2 , 5 , 14 , 42 , 132 , 429 , 1430 , 4862 , 16796 , 58786 , 208012 , 742900 , 2674440 , 9694845 , 35357670 , 129644790 , 477638700 , 1767263190 , 6564120420 , 24466267020 , 91482563640 , 343059613650 , 1289904147324 , 4861946401452 , … 1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440, 9694845, 35357670, 129644790, 477638700, 1767263190, 6564120420, 24466267020, 91482563640, 343059613650, 1289904147324, 4861946401452, … 1,1,2,5,14,42,132,429,1430,4862,16796,58786,208012,742900,2674440,9694845,35357670,129644790,477638700,1767263190,6564120420,24466267020,91482563640,343059613650,1289904147324,4861946401452,

满足递推式
C n + 1 = C 0 C n + C 1 C n − 1 + . . . + C n C 0 ( n − 3 ) C n = n 2 ( C 3 C n − 1 + C 4 C n − 2 + . . . + C n − 1 C 3 ) \begin{aligned} &C_{n+1} = C_{0}C_{n}+C_{1}C_{n-1}+...+C_{n}C_{0}\\ &(n-3)C_n = \frac{n}{2} ( C_{3}C_{n-1}+C_{4}C_{n-2}+...+C_{n-1}C_{3})\\ \end{aligned} Cn+1=C0Cn+C1Cn1+...+CnC0(n3)Cn=2n(C3Cn1+C4Cn2+...+Cn1C3)
f ( n ) = ∑ i = 0 n − 1 f ( i ) ∗ f ( n − i − 1 ) = C 2 n m n + 1 = C 2 n n − C 2 n n − 1 \begin{aligned} f(n) &= \sum_{i=0}^{n-1} f(i)*f(n-i-1) \\ & = \frac{C_{2n}^{m}}{n+1} \\ & = C_{2n}^{n}-C_{2n}^{n-1} \end{aligned} f(n)=i=0n1f(i)f(ni1)=n+1C2nm=C2nnC2nn1

通过状态转移方程简单理解一下卡特兰数:
f [ i ] [ j ] = f [ i ] [ j − 1 ] + f [ i − 1 ] [ j ] f[i][j]=f[i][j-1]+f[i-1][j] f[i][j]=f[i][j1]+f[i1][j]
输出递推矩阵。
其实每个数字就是上方和左方的数字加和,类似于杨辉三角。
杨辉三角是上方和左上方的数字加和。
在这里插入图片描述

ll f[N][N];
int main(){
	scanf("%d",&n);
	for(int i=0;i<=n;i++)	f[0][i]=1;
	for(int i=1;i<=n;i++)
		for(int j=i;j<=n;j++)
			f[i][j]=f[i][j-1]+f[i-1][j];
	printf("%lld",f[n][n]);
}
int solve1() {
    f1[0] = f1[1] = 1;
    cin >> n;
    for(int i = 2; i <= n; i++) 
        for(int j = 0; j < i; j++) 
            f1[i] += (f1[j] * f1[i-j-1]);   //f(n)=f(0)f(n-1)+f(1)f(n-2)+...+f(n-1)f(0)  
    printf("%lld\n",f1[n]);
    return 0;
}

//公式2:
int solve2() {
    f2[0] = f2[1] = 1;
    cin >> n;
    for(int i = 2; i <= n; i++)
        f2[i] = f2[i - 1] * (4 * i - 2) / (i + 1);  //f(n)=f(n-1)*(4*n-2)/(n+1)
    printf("%lld\n", f2[n]);
    return 0;
}

//公式3:
int solve3() {
	cin >> n;
    for(int i = 1; i <= 2 * n; i++) {
        f[i][0] = f[i][i] = 1;
        for(int j = 1; j < i; j++)
            f[i][j] = f[i - 1][j] + f[i - 1][j - 1];     //f(n)=c(2n,n)/(n+1)
    }
    printf("%lld",f[2 * n][n] / (n + 1));
    return 0;
}

应用

P1044 [NOIP2003 普及组] 栈

进出栈问题,问有多少种不同的生成序列的方式,手模一下发现满足卡特兰数

P1641 [SCOI2010]生成字符串

把 n 个 1 和 m 个 0 组成字符串,要求组成的字符串 任意的前 k 个字符中,1 的个数不能少于 0 的个数。求满足要求的字符串共有多少个。
C 2 n n C_{2n}^{n} C2nn种情况,但是 C 2 n n − 1 C_{2n}^{n-1} C2nn1种不合法,满足卡特兰数的递推。

P1754 球迷购票问题

一个A买票后售票处会积累50元钱,一个B买票需要售票处找零50元钱。
说明在一个B买票前至少需要一个A买过票,那么我们就可以将A看作左括号,B看作右括号。
问题就是要求合法得括号匹配,即Catalan数

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值