组合数学是离散数学中的重要部分,早在17世幻就开始了这类课题的研究,当时是在赌博游戏的研究中出现了组合问题。

个体的计数可以求解许多问题,如确定算法的复杂度、分配能满足需求的电话号码,计算机系统中允许使用的密码…

计算原理

加法原理

如果完成第一项任务有n1n_1n1​种方式,完成第二项任务有n2n_2n2​种方式,并且这些任务不能同时完成,那么完成第一或第二项任务有n1+n2n_1+n_2n1​+n2​种方式。

例. 要选一位数学学院的教师或数学专业的学生作为校委会的代表。如果有37位教师和83位数学专业的学生,那么这个代表有多少种不同的选择?
答:完成第一项任务,选一位数学教师,可以有37种方式;完成第二项任务,选一位数学专业的学生,有83种方式,根据加法原理,结果有37+83=120种不同的选择。

乘法原理

假定一个过程被分解两个任务,如果完成第一个任务有n1n_1n1​种方式,完成第二个任务有n2n_2n2​种方式,那么完成这个过程有n1∗n2n_1*n_2n1​∗n2​种方式。

例1. 用一个字母和一个不超过100的正整数给礼堂的座位编号。那么不同的座位最多有多少?
答:给一个座位编号由两个任务组成,从26个字母中选择一个字母分配给它个座位,再从100个正整数中选择一个整数分配给它,可以有26*100=2600种方式。

例2. 如果每个车牌由3个字母后跟3个数字的序列构成,那么有多少个不同的有效的车牌。
答:共有26∗26∗26∗10∗10∗10=1757600026*26*26*10*10*10=17 576 00026∗26∗26∗10∗10∗10=17576000种可能。

混合两种原理的计数问题

许多复杂的计数问题需要同时使用加法原理和乘法原理来求解。

例. 计算机系统的每个用户有一个6~8的字符构成的密码,其中每个字符是一个大写字母或数字,且每个密码至少包含一个数字,有多少可能的密码?

答:题目要求密码至少要包含一个数字,我们可以先算出所有可能的密码数,然后再减去不包含数字密码的数量,解答过程利用了容斥原理。
设PPP是可能的密码总数,P6,P7,P8P_6,P_7,P_8P6​,P7​,P8​分别表过6位、7位、8位可能的密码数。
由乘法原理可得:
P6=366−266P_6=36^6-26^6P6​=366−266
P7=367−267P_7=36^7-26^7P7​=367−267
P8=368−268P_8=36^8-26^8P8​=368−268
再由加法原理可得:P=P6+P7+P8P=P_6+P_7+P_8P=P6​+P7​+P8​

容斥原理

为了正确地计数完成其中一个任务的数量,我们先把完成每个任务的方式数量加起来,然后再减去同时完成两个任务的方式数,这就是容斥原理。

例1. 以1开始或者以00结束的8位二进制符号串有多少个?
设:A={以1开始的8位二进制位}A=\{以1开始的8位二进制位\}A={以1开始的8位二进制位}
B={以00结束的8位二进制位}B=\{以00结束的8位二进制位\}B={以00结束的8位二进制位}
C={答案}C=\{答案\}C={答案}

C=∣A∪B∣−∣A∩B∣C=|A∪B|-|A∩B|C=∣A∪B∣−∣A∩B∣
A=27,B=26,A∩B=25A=2^7 ,B=2^6, A∩B=2^5A=27,B=26,A∩B=25
C=128+64−32=160C=128+64-32=160C=128+64−32=160

例2.某计算机公司收到了350份计算机毕业生的工作申请书。假如这些申请人中有220人主修的是计算机科学专业,有147人主修的是商务专业,有51人即主修了计算机科学专业又主修了商务专业,那么,有多少个申请人既没有主修计算机科学专业又没有主修商务专业?
根据容斥原理,主修计算机或主修商务专业的学生人数为:∣AUB∣=∣A∣+∣B∣−∣A∩B∣=220+147−51|AUB|=|A|+|B|-|A∩B| =220+147-51∣AUB∣=∣A∣+∣B∣−∣A∩B∣=220+147−51
又根据容斥原理,既没有主修计算机又没有主修商务专业的人数为:350−316=34350-316=34350−316=34

树图

我们可以在某些计数问题中使用数,树的每个分支表示每个可能的选择,用树叶表示可能的结果。

例. 有多少个不含连续两个1的4位二进制串?

排列和组合

许多计数类问题可以通过找到特定大小的集合中不同元素排列的不同方法数来得以解决,其中这些次序是有限制的。有些问题是通过从特定大小的集合元素中选择数量的方法数,这些元素的次序是不受限制的。

排列

从nnn个不同元素中,任取mmm个元素,按照一定的顺序排成一列,叫做从nnn个不同元素中取出mmm个元素的一个排列.
记作:Anm=n(n−1)(n−2)...(n−m+1)=n!(n−m)!A_n^m=n(n-1)(n-2)...(n-m+1)=\frac{n!}{(n-m)!}Anm​=n(n−1)(n−2)...(n−m+1)=(n−m)!n!​
也可以记作:P(n,m)=n(n−1)(n−2)...(n−m+1).P(n,m)=n(n-1)(n-2)...(n-m+1).P(n,m)=n(n−1)(n−2)...(n−m+1).

例1. 在进入竞赛的100个不同的人中有多少种方法选出一个一等奖得主、一个二等奖得主和一个三等奖得主?
答:从100个元素中有序选择3个元素的方法数,即100个元素的集合的3排列数。
因此,答案是:
P(100,3)=100∗99∗98=970200P(100,3)=100*99*98=970 200P(100,3)=100∗99∗98=970200

例2. 字母ABCDEFGH有多少种排列包含串ABC?
解:由于字母ABC必须成组出现,我们通过找6个对象,即组ABC和其它的5个字母进行排列得到答案,答案为 6!=7206!=7206!=720 种方式。

组合

从nnn个不同元素中,任取mmm个元素,并成一组,叫做从nnn个不同元素中取出mmm个元素的一个组合.
组合跟元素的顺序无关。
Cnm=AnmAmm=n(n−1)(n−2)...(n−m+1)m!=n!m!⋅(m−m)!C_n^m=\frac{A_n^m}{A_m^m}=\frac{n(n-1)(n-2)...(n-m+1)}{m!}=\frac{n!}{m!\cdot(m-m)!}Cnm​=Amm​Anm​​=m!n(n−1)(n−2)...(n−m+1)​=m!⋅(m−m)!n!​
证明:
∵Anm=Cnm⋅Amm\because A_n^m=C_n^m\cdot A_m^m∵Anm​=Cnm​⋅Amm​,∴Cnm=AnmAmm\therefore C_n^m=\frac{A_n^m}{A_m^m}∴Cnm​=Amm​Anm​​

例. A43=C43⋅A33A_4^3=C_4^3\cdot A_3^3A43​=C43​⋅A33​,C43==A43A33C_4^3==\frac{A_4^3}{A_3^3}C43​==A33​A43​​

组合数恒等式:Cnm=Cnn−mC_n^m=C_n^{n-m}Cnm​=Cnn−m​,如C72=C75.C_7^2=C_7^5.C72​=C75​.
证明 设SSS是nnn个元素的集合。SSS的每个具有rrr个元素的子集AAA对应一个具有n−rn-rn−r个元素的子集A‾\overline AA.

例1. 从一幅52张标准扑克牌中选出5张,共有多少种不同的方法?从一副52张扑克牌中选出47张,又有多少种不同的方法?
问题1:Ans=C(52,5)Ans=C(52,5)Ans=C(52,5)
问题2:Ans=C(52,47)Ans=C(52,47)Ans=C(52,47)

例2. 为开发学校的离散数学课程要选出一个委员会,如果数学系有9个教师,计算机科学系有11个教师。而这个委员会由3个数学系的教师和4个计算机科学系的教师组成,那么有多少种选择方式?
Ans=C(9,3)∗C(11,4)=84∗330=27720Ans=C(9,3)*C(11,4)=84*330=27 720Ans=C(9,3)∗C(11,4)=84∗330=27720

有重复的排列

定理: 具有nnn个物体的集合允许重复的rrr排列数是nrn^rnr.
例. 用英文字母可以构成多少个rrr位字符串?
答:存在26r26^r26r个rrr位字符串。

有重复的组合

定理: nnn个元素的集合中允许重复的rrr组合有 Cn+r−1r=Cn+r−1n−1C_{n+r-1}^r=C_{n+r-1}^{n-1}Cn+r−1r​=Cn+r−1n−1​个。

例. 从包含1美元、2美元、5美元、10美元、20美元、50美元及100美元的钱袋中选5张纸币,有多少种方式?假定不管纸币被选的次序,同种币值的纸币是不加区别的,并且至少每种纸币有5张。

答:题目要求从7个元素集合中取允许重复的5的组合数,我们可以想象在7个盒子中放入5张纸币,
选择5张纸币的方法数对应了6条竖线和5颗星的方法数,因此,选择5张纸币的方法数就是从11个位置选5颗星位置的方法数,这对应从含11个元素的集合中无序地选择5个元素的方法数,总共有C(11,5)种方式。具体如图所示。

具有不可区物体的集合的排列

例.重新排序单词SUCCESS中的字母能多少个不同的串?
答:这个单词某些字母是重复的,答案并不是7个字母的排列数。
这个单词包含了3个S,2个C,1个U,和1个E。
3个S可以用C73C_7^3C73​种不同的方式放在7个位置中;2个C用C42C_4^2C42​ 种方式放入剩下的4个空位中;1个U用C21C_2^1C21​种方式放到剩下的2个空位中;还剩1个E,有C1C_1C1​种方式放下最后一个空位中。
Answer=C73⋅C42⋅C21⋅C11=420.Answer=C_7^3\cdot C_4^2 \cdot C_2^1 \cdot C_1^1=420.Answer=C73​⋅C42​⋅C21​⋅C11​=420.

将物体放入盒子中

可辨别的物体和可辨别的盒子

例. 有多少种把52张扑克牌发给4个人使得每个人5张牌?
答:使用乘法原理,第一个1得到5张牌有C525C_{52}^5C525​种方式,第二个人有C475C_{47}^5C475​ 种方式…第四个人可以有C375C_{37}^5C375​ 种方式,因此发给4个人每人5张牌的方式总数是:C525⋅C475⋅C425⋅C375C_{52}^5\cdot C_{47}^5 \cdot C_{42}^5 \cdot C_{37}^5C525​⋅C475​⋅C425​⋅C375​

不可辨别的物体与可辨别的盒子

例. 将10个不可辨别的球放入8个可辨别的桶里,共有多少种不同的方法?
答:将10个不可辨别的球放入8个可辨别的桶里的方法数等于在允许重复计数的情冲下,从8个元素的集合中取出10组合的个数,即有重复的组合,因此有 C8+10−110=C1710=19448C_{8+10-1}^{10}=C_{17}^{10}=19 448C8+10−110​=C1710​=19448

可辨别的物体与不可辨别的盒子

例. 将4个不同的雇员安排在3间不可辨别的办公室,有多少种方式?其中每间办公室可以安排任意个数的雇员。
解:集合的划分,设S(4,n)(1<=n<=4)为将4个雇员放入到n个办公室(划分成n个集合)
根据加法原理:
Ans=S(4,3)+S(4,2)+S(4,1)=6+7+1=14种。

上述所说的问题称为第二类Stirling数,定义如下:将nnn个有区别的物体放入mmm个相同的盒子里,且没有空盒子
设S(n,m)S(n,m)S(n,m)为将nnn个有区别的物体放入mmm个相同的盒子里且没有空盒的方案数量;
{S(n,0)=0,(m=0)S(n,1)=1,(m=1)S(n,n)=1S(n,k)=0,(k>n)S(n,m)=m⋅S(n−1,m)+S(n−1,m−1),(1<m<n)\begin{cases} S(n,0)=0,\ (m=0) \ \\S(n,1)=1,\ (m=1) \\S(n,n)=1 \\S(n,k)=0 ,(k>n) \\S(n,m)=m\cdot S(n-1,m)+S(n-1,m-1) ,\ \ (1<m<n) \end{cases}⎩⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎧​S(n,0)=0, (m=0) S(n,1)=1, (m=1)S(n,n)=1S(n,k)=0,(k>n)S(n,m)=m⋅S(n−1,m)+S(n−1,m−1),  (1<m<n)​
上面的递归公式的第1行至第4行在编写程序时可作为边界条件进行初始化;

简单说一下第5行的公式S(n,m)=m⋅S(n−1,m)+S(n−1,m−1)S(n,m)=m\cdot S(n-1,m)+S(n-1,m-1)S(n,m)=m⋅S(n−1,m)+S(n−1,m−1)的证明过程
假定nnn个元素的集合中包含某个元素aaa,那么S(n,m)S(n,m)S(n,m)这个问题的求解可划分为两个子问题:
子问题1:某个盒子只放元素aaa的划分方案,递归地求解S(n−1,m−1)S(n-1,m-1)S(n−1,m−1)即可。(放在哪个盒子里都一样,盒子不可区分)
子问题2:某个盒子不仅仅只放元素aaa的划分方案,单独把aaa元素拿出来,先求解出n−1n-1n−1个元素放到m个盒子的方案数,即递归地求解S(n−1,m)S(n-1,m)S(n−1,m)的解,因为元素aaa和其它元素都是可区分的,元素aaa可以放到S(n−1,m)S(n-1,m)S(n−1,m)划分好的任意一个盒子内,根据加法原理,总共有m种放法,即m⋅S(n−1,m)m\cdot S(n-1,m)m⋅S(n−1,m)。

不可辨别的物品和不可辨别的盒子

例-放苹果
将nnn个同样的苹果和mmm个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?

答:
设f(n,m)f(n,m)f(n,m)为放nnn个不可辨别的物品放入到mmm个不可辨别的盒子里的方案数量。
f(n,m)={1,(n=1orn=0)1,(m=1)f(n,n),(m>n)f(n,m−1)+f(n−m,m),(m<=n)f(n,m)=\begin{cases} 1 ,\ (n=1 \ or \ n=0) \\1,\ (m=1) \\ f(n,n),\ (m>n) \\ f(n,m-1)+f(n-m,m)\ \ ,\ (m<=n)\end{cases}f(n,m)=⎩⎪⎪⎪⎨⎪⎪⎪⎧​1, (n=1 or n=0)1, (m=1)f(n,n), (m>n)f(n,m−1)+f(n−m,m)  , (m<=n)​
关于第4行公式f(n,m)=f(n,m−1)+f(n−m,m)f(n,m)=f(n,m-1)+f(n-m,m)f(n,m)=f(n,m−1)+f(n−m,m)的解释,同样地,把f(n,m)f(n,m)f(n,m)拆分成两个子问题:
子问题1:允许至少有一个盘子是空着,递归地求解f(n,m−1)f(n,m-1)f(n,m−1)的值;
子问题2:不允许有盘子是空着,意味着每个盘子都至少放一个苹果,即mmm个盘子放mmm个苹果,还剩下n−mn-mn−m个苹果,递归地求解f(n−m,m)f(n-m,m)f(n−m,m)的值即可;
所以f(n,m)=f(n,m−1)+f(n−m,m).f(n,m)=f(n,m-1)+f(n-m,m).f(n,m)=f(n,m−1)+f(n−m,m).

将nnn个不可辨别的物体放入kkk个不可辨别的盒子,等价于将正整数nnn划分成jjj个正整数相加的方案数。

生成排列和组合

前面我们已经学习了各种类型的排列和组合的计数方法, 但是有时候需要生成排列和组合,而不仅仅是计数。

第一,假设一个销售商必须访问6个城市。应该按照什么顺序访问这些城市而使得总的旅行时间最少?一种方法就是确定6!=720种不同顺序的访问时间并且选择具有最小旅行时间的访问顺序。

第二,假定6个数的集合中某些数的和是100.找出这些数的一种方法就是生成所有26=64个子集并且检查它们的元素和。

生成排列

生成nnn个最小正整数的排列,排列集合的顺序以字典顺序为基础的,对于某个k,1≤k≤n,a1=b1,a2=b2,...,ak−1=bk−1k,1≤k≤n,a_1=b_1,a_2=b_2,...,a_{k-1}=b_{k-1}k,1≤k≤n,a1​=b1​,a2​=b2​,...,ak−1​=bk−1​并且ak<bka_k<b_kak​<bk​,那么排列a1a2...ana_1a_2...a_na1​a2​...an​在排列b1b2...bkb_1b_2...b_kb1​b2​...bk​的前边。

例.集合1,2,3,4,5{1,2,3,4,5}1,2,3,4,5的排列234152341523415在排列235142351423514的前边,因为这些排列在在前两位相同,但第一排列在第三位置中的数是444,小于第二个排列在第三位置中的数555。类似地,排列415324153241532在排列521435214352143的前边。

如何根据给定的排列生成下一个排列?
对于给定的排列a1a2...ana_1a_2...a_na1​a2​...an​,首先找到整数aja_jaj​和aj+1a_{j+1}aj+1​使得aj<aj+1a_j<a_{j+1}aj​<aj+1​且aj+1>aj+2>...>an.a_{j+1}>a{j+2}>...>a_n.aj+1​>aj+2>...>an​.
把aj+1,aj+2,...ana_{j+1},a_{j+2},...a_naj+1​,aj+2​,...an​中大于aja_jaj​的最小的整数放到第jjj个位置,再按照递增顺序重新填充其余的整数。

例. 在362541后面按字典序的下个一最大的排列是什么?
答:找到使得aj<aj+1a_j<a{j+1}aj​<aj+1的一对整数:a3=2,a4=5a_3=2,a_4=5a3​=2,a4​=5,在541中找出一个数 4 大于a3a_3a3​的值并填入a3a_3a3​的位置,{2,5,1}再按照递增的顺序填入a4a_4a4​到a6a_6a6​的位置中,排列为364125。

实现代码:

//算法过程:根据当前的序列求出下一个排列的序列,递归地调用整个过程 #include <iostream>
#include <algorithm>
using namespace std;void permutation(int a[],int n,int rr){for(int i=1;i<=rr;i++)cout<<a[i]<<' ';cout<<endl; //从右往左(从低位到高位),找到下标a_j<a_j+1 int j=n-1;while(a[j]>a[j+1]&&j>0) j--;//判断当前是否是最后一个序列,是则跳出递归调用 if(j==0) return ; //ak是在aj右边大于aj的最小整数int k=n;while(a[j]>a[k]) k--; //交换ak和ajswap(a[j],a[k]); int r=n;    int s=j+1;while(r>s){             swap(a[r],a[s]);r--;s++;}  //sort(a+j+1,a+n+1); permutation(a,n,rr);
}int main(){int a[]={0,1,2,3,4,5,6,7,8,9};permutation(a,9,9);   return 0;
}

算法思路:
1.找到aja_jaj​的位置使得aj<aj+1a_j<a{j+1}aj​<aj+1;
2.在aj+1a_{j+1}aj+1​到ana_nan​中找出一个数aka_kak​的值使得ak>aja_k>a_jak​>aj​.
3.对aj+1a_{j+1}aj+1​到ana_nan​范围的值进行从小到大排序,又因为aj+1a_{j+1}aj+1​到ana_nan​的值本来是已经是一个从大到小排好序的序列,从降序的序列变为升序的序列,只需依次交换前后两个位置的值即可。

除了用上述的算法过程外,我们还可以使用C++中的STL来生成下一个序列。

 //代码来源:算法竞赛入门经典 第二版
#include<cstdio>
#include<algorithm> //包含next_permutation
using namespace std;
int main( ) {  int n, p[10];  scanf("%d", &n);  for(int i = 0; i < n; i++) scanf("%d", &p[i]);  sort(p, p+n);   //排序,得到p的最小排列  do {    for(int i = 0; i < n; i++)  printf("%d ", p[i]);     //输出排列p    printf("\n"); } while(next_permutation(p, p+n)); //求下一个排列  return 0;}

更多的使用方法,可查看链接:生成下一个排列使用方法

康托展开
具体内容请查看链接:康托展开

生成组合

怎样可以生成一个有穷集的元素的所有组合呢?
由于一个组合就是生成的一个子集,我们可以利用在{a1,a2,…an}\{a1 , a2,…an\}{a1,a2,…an}和nnn位二进制位之间的对应.

如果元素aka_kak​在子集中,对应的二迸制串在位置kkk为1,如果aka_kak​不在子集中,对应的二进制串在位置kkk为0.

如果可以列出所有的n位二进制串,那么通过在子集和二进制串之间的对应就可以列出所有的子集。
如何通过当前的二进制串找到下一个二进制串?
假设有nnn个元素,它的二进制串是一个0到2n−12^{n-1}2n−1之间的二进制展开式,首先确定从右边起第一个不是1的位置aka_kak​,把aka_kak​的0变成1,再把ak+1a_{k+1}ak+1​到ana_nan​的二进制数全变为0.

例. 找出在100010 0111后面的下一个二进位串.
答 这个串从右边数不是1的第1位是从右边起的第4位。把这一位变成1并且将它后面所有的位变成0.这就生成了下一个最大的二进位为100010 1000.

二项式系数

二项式定理:

以求(x+y)3(x+y)^3(x+y)3为例.
(x+y)3=(x+y)(x+y)(x+y)(x+y)^3=(x+y)(x+y)(x+y)(x+y)3=(x+y)(x+y)(x+y),求项x3,x2y,xy2,y3x^3,x^2y,xy^2,y^3x3,x2y,xy2,y3的系数。
以求xy2xy^2xy2的系数为例,取两个yyy相乘得到y2y^2y2,再同另一个xxx相乘得到xy2xy^2xy2,总共有C32=3C_3^2=3C32​=3种不同的方式。下图显示了如何取得xy2xy^2xy2的过程,也就是从3个yyy中取2个yyy的组合数。

杨辉三角

帕斯卡恒等式也称为杨辉三角,帕斯卡恒等式的定义如下:
设nnn和kkk是满足n≥kn\geq kn≥k的正整数,那么有:Cn+1k=Cnk−1+Cnk.C_{n+1}^k=C_n^{k-1}+C_n^k.Cn+1k​=Cnk−1​+Cnk​.

证明 假设TTT是包含n+1n+1n+1个元素的集合,令aaa是TTT的一个元素且S=T−{a}S=T-\{a\}S=T−{a},TTT包含kkk个元素的子集有Cn+1kC_{n+1}^kCn+1k​个。

将“TTT包含kkk个元素的子集个数”拆分成两个包含aaa和不包含aaa的子问题。
情况1: 划分的子集包含aaa,问题变成了“求集合SSS包含k−1k-1k−1个元素的子集个数”,有Cnk−1C_{n}^{k-1}Cnk−1​个,因为包含元素aaa,所以是k−1k-1k−1,元素aaa可以放到Cnk−1C_{n}^{k-1}Cnk−1​个划分中的任意一个划分。

情况2: 划分的子集不包含aaa,问题就变成了“求集合SSS划分kkk个元素的子集个数”,答案为CnkC_n^kCnk​

通过初始化Cn0=Crr=1,(0≤r≤n)C_n^0=C_r^r=1,\ (0\leq r\leq n)Cn0​=Crr​=1, (0≤r≤n),使用帕斯卡恒等式通过递推运算,可以算出所有的组合数Cnr,(0≤r≤n)C_n^r\ ,(0\leq r\leq n)Cnr​ ,(0≤r≤n)。具体如下图所示。

卡特兰数

卡特兰数的相关案例和应用很多,比如说二叉树的计数、括号匹配、出栈序列和正多边形的三角剖分,下面我们以书本上的二叉树的计数和正多边形的三角剖分为例讲解。

例1.树的计数
问题:具有nnn个结点的不同形态的二叉树有多少棵?
下图给出了当n=2,n=3,nn=2,n=3,nn=2,n=3,n的一般情形的情况。

设CnC_nCn​为nnn个,根据左右孩子结点数的讨论,可以递归地定义为:
Cn=C0Cn−1+C1Cn−2++C2Cn−3+...+Cn−2C1+Cn−1C0.0C_n=C_0C_{n-1}+C_1C_{n-2}++C_2C_{n-3}+...+C_{n-2}C_1+C_{n-1}C_0.0Cn​=C0​Cn−1​+C1​Cn−2​++C2​Cn−3​+...+Cn−2​C1​+Cn−1​C0​.0
需要注意的是,根节点占用了一个节点,所以左右孩子 的节点数量相加为n−1n-1n−1。

当n=6n=6n=6时,C6=C0C5+C1C4+C3C2+C2C3+C4C1+C5C0C_6=C_0C_5+C_1C_4+C_3C_2+C_2C_3+C_4C_1+C_5C_0C6​=C0​C5​+C1​C4​+C3​C2​+C2​C3​+C4​C1​+C5​C0​
因为上述的公式中有很多重复求解的子问题,在编写程序递归求解时,可以使用记忆化搜索优化。

当然,也可以直接使用公式求解:
含有nnn个结点且不相似的二叉树有 C2nn⋅1n+1C_{2n}^n \cdot \frac{1}{n+1}C2nn​⋅n+11​ 棵。
这就是著名的卡特兰数(Catalan number)
注:编写程序求解组合数建议使用上述的杨辉三角来求解。

补充说明: 在初赛时,如果记不住卡特兰数公式,或者解题的公式有递归调用关系的,可以手动模拟递归求解的过程,先求解(枚举)出某个小的子问题的解,再根据公式求出更大的子问题的解,最后根据依赖关系求出最终解。

例2.正多边形的三角剖分
问题:在一个凸n边形中,通过不相交于n边形内部的对象线,把n边形拆分成若干个三角形。例如五边形有如下五种拆分的方案。

思路:
一个正N边形可以将其拆分成三个部分,固定某一条边(P1,Pn),和剩于的点组成一个三角形,①部分组成的三角形,及②、③部分组成的多边形。原多边形被拆分为两个子问题②和③。

将①看成是根节点, ②和③看成树的计数中的左右孩子结点,思路和树的计数是一样的!

更多关于卡特兰数的内容,请查看下面的链接:
1.https://zhuanlan.zhihu.com/p/31317307
2.https://zhuanlan.zhihu.com/p/31526354 (里面有卡特兰数的计算过程)

参考资料来源:《离散数学及其应用 本科教学版 原书第6版》

OI组合数学相关知识点相关推荐

  1. 卫星轨道推演计算相关知识点总结(含欧拉角、旋转矩阵、及各坐标系转化等)

    来源:轨道机动算法的C++实现_shirro123的专栏-CSDN博客 卫星轨道推演计算相关基础知识点总结 一.卫星的运动特性             二.卫星的空间坐标系               ...

  2. 水下机器人_相关知识点

    485转232 SP3485的管脚及功能: Pin1.RO    接收器输出 Pin2.RE 接收器输出使能(低电平有效) Pin3.DE 驱动器输出使能(高电平有效) Pin4.DI 驱动器输入 P ...

  3. js 闭包及其相关知识点理解

    本文结合个人学习及实践,对闭包及相关知识点进行总结记录,欢迎读者提出任何不足之处 一.js变量 二.作用域(scope) 三.[[scope]] 和 scope chain 四.作用域(scope)和 ...

  4. Redis:相关知识点纵观

    这篇文章先简单的介绍一下redis有什么相关知识点,然后再从接下去的一些文章对一些重要的知识点进行总结. 一.Redis 是什么 Redis 是速度非常快的非关系型(NoSQL)内存键值数据库,可以存 ...

  5. 网络流量队列优先级相关知识点

    网络流量队列优先级相关知识点 Qdisc(quick disconnect)快速分离,断开;是一种排队规则,实现对流量的优先级管理. 涉及随机公平队列,令牌桶过滤器,分层令牌桶,FIFO, /* *C ...

  6. Linux安装和管理程序的相关知识点

    Linux安装和管理程序的相关知识点 一.Linux应用程序基础 1.应用程序与系统命令的关系 2.典型的应用程序结构 3.常见软件包封装类型 二.RPM软件包管理工具 1.RPM包管理工具 2.RP ...

  7. rem和css3的相关知识点

    ☆☆☆rem和css3的相关知识点☆☆☆ 一. Web front-end development engineer rem是根据页面的根元素的font-size的一个相对的单位,即 html{ fo ...

  8. 一次kafka的offset回退事件及相关知识点

    一次kafka的offset回退事件及相关知识点 原文链接:https://blog.csdn.net/lkforce/article/details/83384747

  9. CSS相关知识点:6种清除浮动和BFC

    文章目录 CSS相关知识点:6种清除浮动和BFC 一.6种清除浮动 1.场景 2.原因 3.清除浮动 (1).给父级设置对应的高度 (2).给父级增加定位absolute (3).将父级也设计成浮动 ...

最新文章

  1. 【Codeforces】427B Prison Transfer(别让罪犯跑了...)
  2. Django项目test中的mock概述
  3. 链表排序(冒泡、选择、插入、快排、归并、希尔、堆排序)
  4. python-字符串常用方法、文件简单读写
  5. JavaScript——自定义对话框
  6. pxe装机dhcp获取不到_小白三步装机版重装系统
  7. [MySQL 优化] 移除多余的checksum
  8. windows同时安装python2和3编码_Windows同时安装多个版本,python2和python3,window
  9. . SQL多条件查询存储过程
  10. C++智能指针(一)智能指针的简单介绍
  11. check-lxdialog.sh: line 3: $'\r': command not found
  12. kettle创建mysql资源库
  13. qt中树形控件QTreeWidget的项点击后获取该项的文本
  14. [转]Decide.com是怎么做商品价格预测的
  15. python改变日期的输出格式,关于python:解析日期字符串并更改格式
  16. 此电脑怎么放在桌面上_电脑内部与麦克风的声音怎么同时录制?详细教程在此...
  17. ubuntu16.04下利用ROS启动LPMS-CURS、CURS2等型号IMU;用imu控制turtlesim--教程
  18. php使用二进制判断图片(或文件)真实类型(可判断远程图片)
  19. 谷歌浏览器被2345主页强制绑定
  20. 基于 OpenSSH 的身份认证与密钥管理

热门文章

  1. IDA ,ida pro专业操作手册
  2. 在opencv中如何生成灰度图
  3. Github大文件下载不怕啦
  4. 【GDOI2018模拟7.14】小奇的糖果
  5. 自动化测试工程师应聘要求
  6. 量化金融论文:Astock
  7. 电脑装机完没有efi_win7系统eFI引导从硬盘安装的操作方法
  8. Linux NFS存储服务详解
  9. 厉害了!自己动手也能做一个推荐系统!
  10. 我的电脑开机后桌面上没有图标