卡特兰数(Catalan)及其应用
卡特兰数
大佬博客https://blog.csdn.net/doc_sgl/article/details/8880468
卡特兰数是组合数学中一个常出现在各种计数问题中出现的数列。
卡特兰数前几项为 :
C0=1,C1=1,C2=2,C3=5,C4=14,C5=42,C6=132,C7=429,C8=1430,C9=4862,C10=16796
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, 18367353072152, 69533550916004, 263747951750360, 1002242216651368, 3814986502092304, 14544636039226909, 55534064877048198, 212336130412243110, 812944042149730764, 3116285494907301262, 11959798385860453492, 45950804324621742364, ...
输入一个整数n,计算h(n)。
令h(0)=1,h(1)=1,Catalan数满足递推式:h(n)= h(0)*h(n-1)+h(1)*h(n-2) + ... + h(n-1)*h(0) (n>=2)
例如:
h(2)=h(0)*h(1)+h(1)*h(0)=1*1+1*1=2
h(3)=h(0)*h(2)+h(1)*h(1)+h(2)*h(0)=1*2+1*1+2*1=5
另类递推式:h(n)=h(n-1)*(4*n-2)/(n+1);
递推关系的解为:h(n)=C(2n,n)/(n+1) (n=0,1,2,...)
递推关系的另类解为:h(n)=C(2n,n)-C(2n,n+1)(n=0,1,2,...)
利用递推公式JAVA编大数写的代码:
import java.math.*;
import java.util.*;
public class Main
{
public static void main(String[] args)
{
Scanner cin = new Scanner(System.in);
BigInteger dp[];
dp=new BigInteger[];
dp[]=BigInteger.valueOf();
int i,m;
for(i=; i<=; i++)
{
dp[i]=dp[i-].multiply(BigInteger.valueOf(*i-)).divide(BigInteger.valueOf(i+));
}
while(cin.hasNext())
{
m=cin.nextInt();
if(m==-)
{
break;
}
System.out.println(dp[m]);
}
}
}
卡特兰数的应用
应用1:出栈次序。
一个栈(无穷大)的进栈序列为1,2,3,…,n,有多少个不同的出栈序列?h(n)
常规分析 首先,我们设f(n)=序列个数为n的出栈序列种数。同时,我们假定,从开始到栈第一次出到空为止,这段过程中第一个出栈的序数是k。特别地,如果栈直到整个过程结束时才空,则k=n。首次出空之前第一个出栈的序数k将1~n的序列分成两个序列,其中一个是1~k-1,序列个数为k-1,另外一个是k+1~n,序列个数是n-k。此时,我们若把k视为确定一个序数,那么根据乘法原理,f(n)的问题就等价于——序列个数为k-1的出栈序列种数乘以序列个数为n - k的出栈序列种数,即选择k这个序数的f(n)=f(k-1)×f(n-k)。而k可以选1到n,所以再根据加法原理,将k取不同值的序列种数相加,得到的总序列种数为:f(n)=f(0)f(n-1)+f(1)f(n-2)+……+f(n-1)f(0)。看到此处,再看看卡特兰数的递推式,答案不言而喻,即为f(n)=h(n)= C(2n,n)/(n+1)= c(2n,n)-c(2n,n+1)(n=0,1,2,……)。最后,令f(0)=1,f(1)=1。
非常规分析 对于每一个数来说,必须进栈一次、出栈一次。我们把进栈设为状态‘1’,出栈设为状态‘0’。n个数的所有状态对应n个1和n个0组成的2n位二进制数。由于等待入栈的操作数按照1‥n的顺序排列、入栈的操作数b大于等于出栈的操作数a(a≤b),因此输出序列的总数目=由左而右扫描由n个1和n个0组成的2n位二进制数,1的累计数不小于0的累计数的方案种数。在2n位二进制数中填入n个1的方案数为c(2n,n),不填1的其余n位自动填0。从中减去不符合要求(由左而右扫描,0的累计数大于1的累计数)的方案数即为所求。 不符合要求的数的特征是由左而右扫描时,必然在某一奇数位2m+1位上首先出现m+1个0的累计数和m个1的累计数,此后的2(n-m)-1位上有n-m个 1和n-m-1个0。如若把后面这2(n-m)-1位上的0和1互换,使之成为n-m个0和n-m-1个1,结果得1个由n+1个0和n-1个1组成的2n位数,即一个不合要求的数对应于一个由n+1个0和n-1个1组成的排列。反过来,任何一个由n+1个0和n-1个1组成的2n位二进制数,由于0的个数多2个,2n为偶数,故必在某一个奇数位上出现0的累计数超过1的累计数。同样在后面部分0和1互换,使之成为由n个0和n个1组成的2n位数,即n+1个0和n-1个1组成的2n位数必对应一个不符合要求的数。因而不合要求的2n位数与n+1个0,n-1个1组成的排列一一对应。 显然,不符合要求的方案数为c(2n,n+1)。由此得出输出序列的总数目=c(2n,n)-c(2n,n+1)=c(2n,n)/(n+1)=h(n)。
应用2:括号匹配
n对括号有多少种匹配方式?h(n)
思路:n对括号相当于有2n个符号,n个左括号、n个右括号,可以设问题的解为f(2n)。第0个符号肯定为左括号,与之匹配的右括号必须为第2i+1字符。因为如果是第2i个字符,那么第0个字符与第2i个字符间包含奇数个字符,而奇数个字符是无法构成匹配的。
通过简单分析,f(2n)可以转化如下的递推式 f(2n) = f(0)*f(2n-2) + f(2)*f(2n - 4) + ... + f(2n - 4)*f(2) + f(2n-2)*f(0)。简单解释一下,f(0) * f(2n-2)表示第0个字符与第1个字符匹配,同时剩余字符分成两个部分,一部分为0个字符,另一部分为2n-2个字符,然后对这两部分求解。f(2)*f(2n-4)表示第0个字符与第3个字符匹配,同时剩余字符分成两个部分,一部分为2个字符,另一部分为2n-4个字符。依次类推。
假设f(0) = 1,计算一下开始几项,f(2) = 1, f(4) = 2, f(6) = 5。结合递归式,不难发现f(2n) 等于h(n)。
应用3:矩阵链乘
P=a1×a2×a3×……×an,依据乘法结合律,不改变其顺序,只用括号表示成对的乘积,试问有几种括号化的方案?h(n-1)
思路:可以这样考虑,首先通过括号化,将P分成两个部分,然后分别对两个部分进行括号化。比如分成(a1)×(a2×a3.....×an),然后再对(a1)和(a2×a3.....×an)分别括号化;又如分成(a1×a2)×(a3.....×an),然后再对(a1×a2)和(a3.....×an)括号化。 设n个矩阵的括号化方案的种数为f(n),那么问题的解为 f(n) = f(1)*f(n-1) + f(2)*f(n-2) + f(3)*f(n-3) + f(n-1)*f(1)。f(1)*f(n-1)表示分成(a1)×(a2×a3.....×an)两部分,然后分别括号化。
计算开始几项,f(1) = 1, f(2) = 1, f(3) = 2, f(4) = 5。结合递归式,不难发现f(n)等于h(n-1)。
应用4:出栈序列
一个栈(无穷大)的进栈序列为1,2,3,…,n,有多少个不同的出栈序列?h(n)
思路:这个与加括号的很相似,进栈操作相当于是左括号,而出栈操作相当于右括号。n个数的进栈次序和出栈次序构成了一个含2n个数字的序列。第0个数字肯定是进栈的数,这个数相应的出栈的数一定是第2i+1个数。因为如果是2i,那么中间包含了奇数个数,这奇数个肯定无法构成进栈出栈序列。设问题的解为f(2n), 那么f(2n) = f(0)*f(2n-2) + f(2)*f(2n-4) + f(2n-2)*f(0)。f(0) * f(2n-2)表示第0个数字进栈后立即出栈,此时这个数字的进栈与出栈间包含的数字个数为0,剩余为2n-2个数。f(2)*f(2n-4)表示第0个数字进栈与出栈间包含了2个数字,相当于1 2 2 1,剩余为2n-4个数字。依次类推。
假设f(0) = 1,计算一下开始几项,f(2) = 1, f(4) = 2, f(6) = 5。结合递归式,不难发现f(2n) 等于h(n)。
应用5:n结点二叉树
n个节点构成的二叉树,共有多少种情形?h(n)
思路:可以这样考虑,根肯定会占用一个结点,那么剩余的n-1个结点可以有如下的分配方式,T(0, n-1),T(1, n-2),...T(n-1, 0),设T(i, j)表示根的左子树含i个结点,右子树含j个结点。
设问题的解为f(n),那么f(n) = f(0)*f(n-1) + f(1)*f(n-2) + .......+ f(n-2)*f(1) + f(n-1)*f(0)。假设f(0) = 1,那么f(1) = 1, f(2) = 2, f(3) = 5。
结合递推式,不难发现f(n)等于h(n)。
应用6:不相交线段数
在圆上选择2n个点,将这些点成对连接起来使得所得到的n条线段不相交的方法数?h(n)
思路:以其中一个点为基点,编号为0,然后按顺时针方向将其他点依次编号。那么与编号为0相连点的编号一定是奇数,否则,这两个编号间含有奇数个点,势必会有个点被孤立,即在一条线段的两侧分别有一个孤立点,从而导致两线段相交。设选中的基点为A,与它连接的点为B,那么A和B将所有点分成两个部分,一部分位于A、B的左边,另一部分位于A、B的右边。然后分别对这两部分求解即可。
设问题的解f(n),那么f(n) = f(0)*f(n-2) + f(2)*f(n-4) + f(4)*f(n-6) + ......f(n-4)*f(2) + f(n-2)*f(0)。f(0)*f(n-2)表示编号0的点与编号1的点相连,此时位于它们右边的点的个数为0,而位于它们左边的点为2n-2。依次类推。 f(0) = 1, f(2) = 1, f(4) = 2。结合递归式,不难发现f(2n) 等于h(n)。
应用7:凸多边形三角剖分
求一个凸多边形区域划分成三角形区域的方法数?h(n-2)
思路:这是《离散数学》组合数学中引入卡特兰数概念的例子。以凸多边形的一边为基,设这条边的2个顶点为A和B。从剩余顶点中选1个,可以将凸多边形分成三个部分,中间是一个三角形,左右两边分别是两个凸多边形,然后求解左右两个凸多边形。
设问题的解f(n),其中n表示顶点数,两刀下去,左右两个凸多边形,会有一个公共顶点,总顶点数为n+1,那么f(n) = f(2)*f(n-1) + f(3)*f(n-2) + ......f(n-2)*f(3) + f(n-1)*f(2)。设f(2) = 1,那么f(3) = 1, f(4) = 2, f(5) = 5。结合递推式,不难发现f(n) 等于h(n-2)。
应用8:找零钱
有2n个人排成一行进入剧场。入场费5元。其中只有n个人有一张5元钞票,另外n人只有10元钞票,剧院无其它钞票,问有多少中方法使得只要有10元的人买票,售票处就有5元的钞票找零?h(n)
思路:可以将持5元买票视为进栈,那么持10元买票视为5元的出栈。这个问题就转化成了栈的出栈次序数。由应用2的分析直接得到结果,f(2n) 等于h(n)。
最后我想写一写我自己对于卡特兰数应用的一些理解。h(n)= h(0)*h(n-1)+h(1)*h(n-2) + ... + h(n-1)*h(0) (n>=2) 这个表达式应该是卡特兰数应用中最为本质的。这些用卡特兰数解决的题目都可以将一个问题进行分开统计划分为两个子问题,这两个子问题又可以再进行划分,进行一次次的递归,直到得到最小单位时,把所有的状态都加起来。
卡特兰数(Catalan)及其应用的更多相关文章
- 卡特兰数 Catalan数 ( ACM 数论 组合 )
卡特兰数 Catalan数 ( ACM 数论 组合 ) Posted on 2010-08-07 21:51 MiYu 阅读(13170) 评论(1) 编辑 收藏 引用 所属分类: ACM ( 数论 ...
- 浅谈卡特兰数(Catalan number)的原理和相关应用
一.卡特兰数(Catalan number) 1.定义 组合数学中一个常出现在各种计数问题中出现的数列(用c表示).以比利时的数学家欧仁·查理·卡特兰的名字来命名: 2.计算公式 (1)递推公式 c[ ...
- 卡特兰数 catalan number
作者:阿凡卢 出处:http://www.cnblogs.com/luxiaoxun/ 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留 ...
- 卡特兰数(Catalan Number) 算法、数论 组合~
Catalan number,卡特兰数又称卡塔兰数,是组合数学中一个常出现在各种计数问题中出现的数列.以比利时的数学家欧仁·查理·卡塔兰 (1814–1894)命名. 卡特兰数的前几个数 前20项为( ...
- 卡特兰数 Catalan 笔记
一.公式 卡特兰数一般公式 令h(0)=1,h(1)=1,catalan数满足递推式.h(n) = h(0)*h(n-1)+h(1)*h(n-2) + ... + h(n-1)h(0) (n>= ...
- ACM数论-卡特兰数Catalan
Catalan 原理: 令h(0)=1,h(1)=1,catalan 数满足递归式: (其中n>=2) 另类递推公式: 该递推关系的解为: (n=1,2,3,...) 卡特兰数的应用实质上都是递 ...
- 卡特兰数(Catalan Number) 学习笔记
一.三个简单的问题 1.给定一串长为2n的01序列,其中0和1的数量相等,满足任意前缀中0的个数不少于1的个数,求序列的个数 2.给出一串长为n的序列,按顺序将他们进栈,随意出栈,求最后进出栈的方案 ...
- 【知识总结】卡特兰数 (Catalan Number) 公式的推导
卡特兰数的英文维基讲得非常全面,强烈建议阅读! Catalan number - Wikipedia (本文中图片也来源于这个页面) 由于本人太菜,这里只选取其中两个公式进行总结. (似乎就是这两个比 ...
- 【2020.12.01提高组模拟】卡特兰数(catalan)
题目 题目描述 今天,接触信息学不久的小\(A\)刚刚学习了卡特兰数. 卡特兰数的一个经典定义是,将\(n\)个数依次入栈,合法的出栈序列个数. 小\(A\)觉得这样的情况太平凡了.于是,他给出了\( ...
随机推荐
- MVC——MVP——MVVM
MVC什么样? 从这个图中可以清楚的看到: View:视图层——这里是用户与之交互的界面. Model:模型层——这里面主要就是业务数据,并把数据提供给视图层 Controller:控制器——他的主要 ...
- Java中的引用:强引用、软引用、弱引用、幻象引用(虚引用)
Java语言中,除了原始数据类型的变量(八大基本数据类型),其他都是引用类型,指向各种不同的对象. 理解引用对于我们掌握Java对象生命周期和JVM内部相关机制都是有帮助的. 不同的应用类型,不同之处 ...
- MySQL 日常运维业务账号权限的控制
在MySQL数据库日常运维中,对业务子账号的权限的统一控制十分必要. 业务上基本分为读账号和写账号两种账号,所以可以整理为固定的存储过程,让数据库自动生成对应的库的账号,随机密码.以及统一的读权限,写 ...
- PHP-----PHP程序设计基础教程----第一章PHP开篇
本章内容知识体系如下所示: 一.PHP基础知识 1.1 Web技术 服务器与客户端 服务器:能够提供某种服务的电脑 客户端:想使用服务器所提供服务的电脑 服务器也是一台电脑,必须安装操作系统.否则就是 ...
- 解决 SSH 不能输入中文的问题
有些应用的进程名称可能是中文,还有一些应用创建的目录可以也会是中文,在 SSH 上使用 debugserver 没有办法输入中文的进程名称,也没办法在 SSH 上操作中文的目录,网上试了一些方法,不过 ...
- 利用RTTI实现Delphi的多播事件代理研究
我们知道Delphi的每个对象可以包含多个Property,Property中可以是方法,例如TButton.OnClick属性.Delphi提供的仅仅是 一对一的设置,无法直接让TButton.On ...
- 树莓派安装SimpleCV
开源计算机视觉框架.python2 安装 (http://simplecv.readthedocs.io/en/latest/HOWTO-Install%20on%20RaspberryPi.html ...
- docker inspect获取详细参数的两种方法
docker inspect xx 返回的是一个json格式的数据 以下为部分返回值 [ { "Id": "706813b0da107c4d43c61e3db9da908 ...
- PTA(BasicLevel)-1007素数对猜想
一 问题描述-素数对 让我们定义素数差dn为:dn=pn+1−pn,其中pi是第i个素数.显然有d1=1,且对于n>1有dn是偶数.“素数对猜想”认为“ ...
- BZOJ2039_employ人员雇佣_KEY
题目传送门 网络流,求最小割. 设tot为所有盈利的和,即所有人(不花钱)雇佣. 对于S->i建一条容量为c[i]的边,i->j建一条S[i][j]*2的边,之所以这样建是因为如果不选这个 ...