卡特兰数 [转载]

me 一个童鞋跟 me 提过一个问题:说1-12 这 12 个数,分成 2 组,然后每组按大小排序,其中一组中的数总是比另外一组中对应顺序的数要大,问有多少种情况?me 还真做不出来,他告诉 me 说这是Catalan数。即使他这么说,me 貌似还是不太明白。不过这不影响,me 简单搜索一下这个数(其实me以前就有所耳闻),有好几个用处,简单罗列一下。

平衡括号

平衡括号:在一个合法的算术表达式中可以出现的括号都是平衡括号,更专业一点的说法应该是“所有的左括号和右括号可以建立一对一的对应关系,并且左括号在对应的右括号左侧”。像()(), (())(), (()())(()) 都是平衡括号,但是(()))(, ()())() 就不是平衡括号。

观察一下特点,判断所给的一个括号串是不是平衡很容易:设置一个计数器,初始值为 0,然后从左向右数,遇到左括号 +1,遇到右括号 -1,在过程中不出现负数,并且最终的计数器还是 0,那么就是平衡括号;除此之外就是非平衡括号。

现在的问题是,如果有 n 对括号,问平衡的情况有多少种?暂时可以数一下 n = 1, 2, 3, 4 时的情况:

n = 1: ()
n = 2: ()(),   (())
n = 3: ()()(),  ()(()), (())(), (()()), ((()))
n = 4:()()()(), ()()(()), ()(())(), ()(()()), ()((())), (())()(), (())(()), (()())(), ((()))(), (()()()), (()(())), ((())()), ((()())), (((())))

入栈出栈

问:n 个数入栈出栈,问情况有多少种?

比如全部入进去然后倒退出栈是 1 种;入一个出一个,全部都这样,是 1 种。入栈出栈的情况和n个数相不相同没有关系。因为可以视第一个入栈的为 1,第二个为 2,最后一个为 n。如果是 n 个相同的数的入栈出栈情况,假设数字都是括号,入栈是左括号,出栈是右括号,那么一种入栈出栈情况应该就对应平衡括号中的一种情况,所以,该问题和问题1是等价问题。

走方格

问:一个 n*n 的方格,从左下角走到右上角,只能向右和向上走,但是不能绕过左下角和右上角确定的对角线,问有多少种走法?

如果将向右走看做是入一下栈,向上走是出一下栈,不能绕道对角线以上,也就是一种合法的入栈出栈,从左下角开始到右上角,要入 n 次栈出 n 次栈,所以一种走法对应一种 n 个数的入栈出栈情况,于是,此问题和问题2是等价问题;

二叉树的形状

问:n 个结点的二叉树的形状有多少种?

所谓的二叉树,就是有一个根结点,有棵左子树还有一棵右子树。n = 3: ()()(), ()(()), (())(), (()()), ((())) 时的括号匹配,me 们换个角度看这个表示:第一个成对的括号是树根,括号内部的子串和括号右边的子串依然是平衡括号串,把内部的看做是左子树,把右边的看成是右子树,比如(())()对应的是有一个左节点和一个右节点的二叉树,()()() 表示只有右子树的二叉树(右子树只有一个右结点);如果上面的对应成立(递归证明),那么二叉树的情况就和问题1 是等价问题;

矩阵链乘

问:A = A0 * A1 * A2 * ... * An,Ai 都是矩阵,式子合法,那么问,如果使用括号来改变计算顺序的话,计算方法有多少种?

本来的乘法运算是从左到右运算,me 们将运算使用栈模拟一下:首先将 A0 压入栈底,然后看 A1,和栈顶的 A0 计算结果,栈顶 A0 出栈而结果入栈;看A2,和栈顶元素计算结果,栈顶元素出栈、结果入栈;...如果使用括号改变了顺序,比如A0*(A1*A2)*...看A1的时候,入栈不计算结果,看A2的时候,计算结果,A1出栈结果入栈;...如果这样看来的话,每一种计算顺序,实际上对应一种 A0-A(n-1) 的入栈出栈情况,于是,此问题和问题2等价;

...

有时候上面几个问题的等价不是那么明显,然而上面的几个问题都可以用同一个递推公式来表示:

C0 = 1 ;
Cn = ∑ Ci · C(n-1-i) ;

举例:
C0 = 1; C1 = 1; C2 = 2; C3 = 5; C4 = 14;
C5 = C0C4 + C1C3 + C2C2 + C3C1 + C4C0 = 14+5+4+5+14 = 42

上面的几个问题都是等价问题,所得的数就是 Catalan 数,可以计算出通项公式(可以使用生成函数法):

Cn = C(n,2n)/(n+1)
,其中C(m,n)是 n 个不同的数中取 m 个数形成的组合数;

注:C5 = 42,介貌似是一个灰常有名的数,可以记一下。

时间: 2024-12-28 10:37:58

卡特兰数 [转载]的相关文章

(转载)Catalan数——卡特兰数

Catalan数--卡特兰数 今天阿里淘宝笔试中碰到两道组合数学题,感觉非常亲切,但是笔试中失踪推导不出来后来查了下,原来是Catalan数.悲剧啊,现在整理一下 一.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个的组合数) 问题描

hunnu11562:The Triangle Division of the Convex Polygon(第n个卡特兰数取模)

Problem description   A convex polygon with n edges can be divided into several triangles by some non-intersect diagonals. We denote d(n) is the number of the different ways to divide the convex polygon. For example,when n is 6,there are 14 different

卡特兰数-Catalan数

卡特兰数的含义: 说到卡特兰数,就不得不提及卡特兰数序列,卡特兰数序列是一个整数序列,其通项公式是我们从中取出的就叫做第n个卡特兰数数,前几个卡特兰数数是:1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, -运用卡特兰数可以解决许多实际问题上的计数问题 卡特兰数的几个基本性质以及变形公式:(提示括号一上n一下m表示n中选择m个的组合数) 1.-->> 2. 3. 4. 以上的推导公式为其基本性质总结,

【BZOJ2822】【AHOI2012】树屋阶梯 卡特兰数 python高精度

#include <stdio.h> int main() { puts("转载请注明出处谢谢"); puts("http://blog.csdn.net/vmurder/article/details/43404565"); } 题解: 首先考虑在当前情况下多加一层,那么我们可以枚举最后一层台阶长度来得到答案. 最后得到的是卡特兰数. 代码: f=[0]*60 f[1]=1 n=int(raw_input()) for i in range(2,n+1

hdoj-1023-Train Problem II【卡特兰数】

Train Problem II Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6852 Accepted Submission(s): 3708 Problem Description As we all know the Train Problem I, the boss of the Ignatius Train Station wa

HDU Train Problem II (卡特兰数+大数)

Problem Description As we all know the Train Problem I, the boss of the Ignatius Train Station want to know if all the trains come in strict-increasing order, how many orders that all the trains can get out of the railway.   Input The input contains

hdoj 1023 Train Problem II 【卡特兰数】

Train Problem II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6928    Accepted Submission(s): 3750 Problem Description As we all know the Train Problem I, the boss of the Ignatius Train Stat

HDU 4828 (卡特兰数+逆)

HDU 4828 Grids 思路:能够转化为卡特兰数,先把前n个人标为0.后n个人标为1.然后去全排列,全排列的数列.假设每一个1的前面相应的0大于等于1,那么就是满足的序列,假设把0看成入栈,1看成出栈.那么就等价于n个元素入栈出栈,求符合条件的出栈序列,这个就是卡特兰数了. 然后去递推一下解,过程中须要求逆元去计算 代码: #include <stdio.h> #include <string.h> const int N = 1000005; const long long

poj1095--Trees Made to Order(卡特兰数)

题目链接:点击打开链接 题目大意:按照图中给的编号方式,节点数逐渐增加,所有的点尽量在右子树上,问第m颗树是什么样子的,按照给的模式输出 (左)x(右),如果没有就缺省. 首先对于n个节点的二叉树一共有多少种形态,这刚好符合卡特兰数的值. h(n) = C(2n,n)/(n+1) = C(2n,n) - C(2n,n-1) = h(n-1)*(4n-2)/(n+1) (递推公式).按照递推公式就可以求出对于k个节点二叉树有多少种变化方式. 然后对于求第m颗树,可以先找到第m棵树应该是几个节点,然