Catalan数

Catalan数是一类重要的数,在组合数学中用于计数多种组合结构,如Dyck词、括号表达式、二叉树、不越过对角线的单调路径等。递推公式为h(n) = (4n-2)/(n+1)*h(n-1),n>=2,并有多种应用场景,包括二进制数的特定排列、凸多边形的三角形划分等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

事情是这样的,某天在洛谷题库乱翻题写,突然看到一道普及-的东西【P1044 栈】,觉得啊,可以娱乐一下身心,就点开了,自己水了一下之后,照例围观题解,发现了这是“卡特兰数”的裸题【在此之前也听说过似乎】,然后一脸憧憬地去百度,get以下内容:


Catalan数是用来解决以下类似问题的:

n个1和n个0组成一2n位的2进制数,要求从左到右扫描,1的个数不小于0的个数,试求满足这条件的数有多少?


那么,卡特兰数怎么求呢?


Catalan数的定义令h(1)=1,Catalan数满足递归式:h(n) = h(1)*h(n-1) + h(2)*h(n-2) + ... + h(n-1)h(1),n>=2

该递推关系的解为:h(n) = C(2n-2,n-1)/n,n=1,2,3,...(其中C(2n-2,n-1)表示2n-2个中取n-1个的组合数)


以下提供几种求解方式:

1.h(n)=(4n-2)/(n+1)*h(n-1)  (n>1)  h(0)=h(1)=1

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int n;
double dp[20];
int main() 
{
    scanf("%d",&n);
    dp[0]=dp[1]=1;//卡特兰数列的前两项(和斐波拉契数列没差)
    for(int i=2;i<=n;i++)
    {
        double temp=(4*i-2.0)/(i+1.0);//会有小数部分
        dp[i]=temp*dp[i-1];//卡特兰数列递推式
    }
    printf("%.lf\n",dp[n]);
    return 0;
}


2.

#include<iostream>
#include<cstdio>
#include<cstring>
int f[30];
using namespace std;
int main(){
	int n;
	scanf("%d",&n);
	f[0]=f[1]=1;
	for(int i=2;i<=n;i++){
		for(int j=0;j<i;j++){
			f[i]+=f[j]*f[i-j-1];
		}
	}
	printf("%d\n",f[n]);
	return 0;
}


其实重点应该是应用。。。:【from Wiki】

应用

组合数学中有非常多.的组合结构可以用卡塔兰数来计数。在Richard P. Stanley的Enumerative Combinatorics: Volume 2一书的习题中包括了66个相异的可由卡塔兰数表达的组合结构。以下用Cn=3和Cn=4举若干例:


  • Cn表示长度2n的dyck word的个数。Dyck word是一个有n个X和n个Y组成的字串,且所有的部分字串皆满足X的个数大于等于Y的个数。以下为长度为6的dyck words:
XXXYYY XYXXYY XYXYXY XXYYXY XXYXYY

  • 将上例的X换成左括号,Y换成右括号,Cn表示所有包含n组括号的合法运算式的个数:
((())) ()(()) ()()() (())() (()())

  • Cn表示有n+1个叶子的二叉树的个数。

                                                                      


  • Cn表示所有不同构的含n个分枝结点的满二叉树的个数。(一个有根二叉树是满的当且仅当每个结点都有两个子树或没有子树。)

证明:

令1表示进栈,0表示出栈,则可转化为求一个2n位、含n个1、n个0的二进制数,满足从左往右扫描到任意一位时,经过的0数不多于1数。显然含n个1、n个0的2n位二进制数共有{2n \choose n}个,下面考虑不满足要求的数目.

考虑一个含n个1、n个0的2n位二进制数,扫描到第2m+1位上时有m+1个0和m个1(容易证明一定存在这样的情况),则后面的0-1排列中必有n-m个1和n-m-1个0。将2m+2及其以后的部分0变成1、1变成0,则对应一个n+1个0和n-1个1的二进制数。反之亦然(相似的思路证明两者一一对应)。

从而C_n = {2n \choose n} - {2n \choose n + 1} = \frac{1}{n+1}{2n \choose n}。证毕。


  • Cn表示所有在n × n格点中不越过对角线的单调路径的个数。一个单调路径从格点左下角出发,在格点右上角结束,每一步均为向上或向右。计算这种路径的个数等价于计算Dyck word的个数: X代表“向右”,Y代表“向上”。下图为n = 4的情况:
  •                                                                        


  • Cn表示通过连结顶点而将n + 2边的凸多边形分成三角形的方法个数。下图中为n = 4的情况:

                                                                                


  • Cn表示对{1, ..., n}依序进出栈的置换个数。一个置换w是依序进出栈的当S(w) = (1, ..., n), 其中S(w)递归定义如下:令w = unv,其中nw的最大元素,uv为更短的数列;再令S(w) =S(u)S(v)n,其中S为所有含一个元素的数列的单位元。


  • Cn表示集合{1, ..., n}的不交叉划分的个数. 


  • Cn表示用n个长方形填充一个高度为n的阶梯状图形的方法个数。下图为 n = 4的情况:

                                                                                          


所以真的是裸题了。。。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值