Catalan (卡特兰数)

前置知识:

1、排列数公式: A n m = n ( n − 1 ) ( n − 2 ) . . . ( n − m + 1 ) A^m_n=n(n-1)(n-2)...(n-m+1) Anm​=n(n−1)(n−2)...(n−m+1)​​

引入阶乘 n ! n! n!以后,排列数公式变形如下:

A n m = n ( n − 1 ) ( n − 2 ) . . . ( n − m + 1 ) = n ( n − 1 ) ( n − 2 ) . . . ( n − m + 1 ) ( n − m ) . . . 3 ∗ 2 ∗ 1 ( n − m ) . . . 3 ∗ 2 ∗ 1 = n ! ( n − m ) ! A^m_n=n(n-1)(n-2)...(n-m+1)=\frac{n(n-1)(n-2)...(n-m+1)(n-m)...3*2*1}{(n-m)...3*2*1}=\frac{n!}{(n-m)!} Anm​=n(n−1)(n−2)...(n−m+1)=(n−m)...3∗2∗1n(n−1)(n−2)...(n−m+1)(n−m)...3∗2∗1​=(n−m)!n!​

**注意:**为了保证公式在 n = m n=m n=m时成立,特规定 0 ! = 1 0!=1 0!=1

2、组合数公式: C n m = A n m A m m = n ( n − 1 ) ( n − 2 ) . . . ( n − m + 1 ) m ! = n ! m ! ( n − m ) ! C^m_n=\frac{A^m_n}{A^m_m}=\frac{n(n-1)(n-2)...(n-m+1)}{m!}=\frac{n!}{m!(n-m)!} Cnm​=Amm​Anm​​=m!n(n−1)(n−2)...(n−m+1)​=m!(n−m)!n!​​

其它性质:

C n m = C n n − m C^m_n=C^{n-m}_n Cnm​=Cnn−m​​​​​ (对称)

C n m = C n − 1 m + C n − 1 m − 1 C^m_n=C^m_{n-1}+C^{m-1}_{n-1} Cnm​=Cn−1m​+Cn−1m−1​​

C n 0 + C n 1 + C n 2 + . . . + C n n = 2 n C^0_n+C^1_n+C^2_n+...+C^n_n=2^n Cn0​+Cn1​+Cn2​+...+Cnn​=2n

注意: C n 0 = 1 C^0_n=1 Cn0​=1


Catalan:

卡特兰数是组合数学中的一种著名数列,通常用如下通项式表示(为了不与组合数C 冲突,本文用 f f f​ 表示卡特兰数): f ( n ) = C 2 n n n + 1 f(n)=\frac{C^n_{2n}}{n+1} f(n)=n+1C2nn​​​​​

通项式变形: f ( n ) = C 2 n n − C 2 n n − 1 f(n)=C^n_{2n}-C^{n-1}_{2n} f(n)=C2nn​−C2nn−1​

卡特兰数递推式: f ( n ) = ∑ i = 0 n − 1 f ( i ) ∗ f ( n − i − 1 ) f(n)=\sum\limits^{n-1}_{i=0}f(i)*f(n-i-1) f(n)=i=0∑n−1​f(i)∗f(n−i−1)​

与卡特兰数相关的问题:

1、 1 , 2 , . . . , n 1,2,...,n 1,2,...,n经过一个栈,形成的合法出栈序列的数量为 c a t n cat_n catn​

2、 n n n个左括号和 n n n个右括号组成的合法括号序列的数量为 c a t n cat_n catn​

3、 n n n个结点构成的不同二叉树的数量为 c a t n cat_n catn​

4、买票排队问题,票价为 x x x元,现在有 n n n个顾客用面值为 x x x的钱币购买,还有 n n n个顾客用面值为 x ∗ 2 x*2 x∗2的钱币购买,商家起初没有钱找零。此时形成的合法排队(商家可以给所有该找零的顾客找零)方案数量为 c a t n cat_n catn​

5、 n n n边形 ( n > = 3 ) (n>=3) (n>=3)切割 n − 3 n-3 n−3刀,要求剩下的图形都为三角形,切割的方案数为 c a t n cat_n catn​

6、在平面直角坐标系上,每一步只能向上或向右走,从 ( 0 , 0 ) (0,0) (0,0)走到 ( n , n ) (n, n) (n,n)并且除了两个端点外不接触 y = x y=x y=x的路线数量为 2 c a t n − 1 2cat_{n-1} 2catn−1​

实际做Catalan数的题目时,数值会非常大,通常配合高精度运算,通过阶乘分解的方法可以省去除法运算,只用高精度乘法模拟即可

阶乘分解

Acwing197 阶乘分解

​ 给定整数 N ( 1 < = N < = 1 0 6 ) N(1<=N<=10^6) N(1<=N<=106),试把阶乘 N ! N! N!分解质因数,按照算数基本定理的形式输出分解结果中的 p i p_i pi​和 c i c_i ci​即可( p i p_i pi​代表第 i i i个质因子, c i c_i ci​代表第 i i i个因子的个数)

​ 若 1 ∼ N 1\thicksim N 1∼N每个数分别分解质因数,再把结果合并,时间复杂度过高,为 O ( N N ) O(N\sqrt{N}) O(NN ​)。显然, N ! N! N!的每个质因子都不会超过 N N N,我们可以先筛选出 1 ∼ N 1\thicksim N 1∼N 的每个质数 p p p,然后考虑N!中一共包含多少个质因子 p p p​

​ N ! N! N!​中质因子 p p p​ 的个数就等于 1 ∼ N 1\thicksim N 1∼N​每个数包含质因子 p p p​ 的个数之和。在 1 ∼ N 1\thicksim N 1∼N​中, p p p​ 的倍数,即至少包含 1 1 1​ 个质因子 p p p​ 的显然有 ⌊ N p ⌋ \lfloor \frac{N}p \rfloor ⌊pN​⌋​个。而 p p p​ 的倍数,即至少包含 2 2 2​个质因子 p p p​ 的有 ⌊ N p 2 ⌋ \lfloor \frac{N}{p^2} \rfloor ⌊p2N​⌋​个。不过其中的 1 1 1​个质因子已经在 ⌊ N p ⌋ \lfloor \frac{N}p \rfloor ⌊pN​⌋​里统计过,所以只需要再统计第 2 2 2​个质因子,即累加上 ⌊ N p 2 ⌋ \lfloor \frac{N}{p^2} \rfloor ⌊p2N​⌋​,而不是 2 ∗ ⌊ N p 2 ⌋ 2 *\lfloor \frac{N}{p^2} \rfloor 2∗⌊p2N​⌋​。

​ 综上所述, N ! N! N!中质因子 p p p 的个数为:

⌊ N p ⌋ + ⌊ N p 2 ⌋ + ⌊ N p 3 ⌋ + . . . + ⌊ N p ⌊ l o g p N ⌋ ⌋ = ∑ p k ⩽ N ⌊ N p k ⌋ \lfloor \frac{N}p \rfloor+\lfloor \frac{N}{p^2} \rfloor+\lfloor \frac{N}{p^3} \rfloor+...+\lfloor \frac{N}{p^{\lfloor {log_pN} \rfloor}} \rfloor=\sum\limits _{p^k \leqslant N} \lfloor \frac{N}{p^k} \rfloor ⌊pN​⌋+⌊p2N​⌋+⌊p3N​⌋+...+⌊p⌊logp​N⌋N​⌋=pk⩽N∑​⌊pkN​⌋​​

​ 对于每个 p p p,只需要 O ( l o g N ) O(logN) O(logN)的时间计算上述和式。故对整个 N ! N! N!分解质因数的时间复杂度为 O ( N l o g N ) O(NlogN) O(NlogN)​

1、火车进出栈问题

Acwing130 火车进出栈问题

卡特兰数: f ( n ) = C 2 n n n + 1 f(n)=\frac{C^n_{2n}}{n+1} f(n)=n+1C2nn​​ , C 2 n n = ( 2 n ) ! n ! n ! C^n_{2n} = \frac{(2n)!}{n!n!} C2nn​=n!n!(2n)!​

把 ( 2 n ) ! (2n)! (2n)!的所有质因子 p i p_i pi​以及数量 c i c_i ci​​ 分别存放到两个数组中。用同样的方法计算出 n ! n ! n!n! n!n!并从这两个数组的对应位置减去对应数量。之后再分解 n + 1 n+1 n+1,也从这两个数组中减去对应数量。(结果为所有分母都被约分掉,相当于去掉了除法操作,证明略)

最后高精度乘法模拟两个数组运算即可

/*************************************************************************> File Name: 130.c> Author: Luzelin> Mail: > Created Time: Sun Nov 28 10:59:19 2021************************************************************************/#include <stdio.h>#define N 60000int prime[N * 2 + 5], nums[N * 2 + 5], cnt;//线性筛出小于等于n*2的所有质数
void Get_prime(int n) {for (int i = 2; i <= n; ++i) {if (prime[i] == 0)  prime[cnt++] = i;for (int j = 0; j < cnt && i * prime[j] <= n; ++j) {prime[i * prime[j]] = 1;if (i % prime[j] == 0)  break;}}return ;
}//阶乘分解
//n!中存在质因子p的个数
int Get_div(int n, int p) {int cnt = 0;//除数乘p等价于被除数除pwhile (n > 1) {cnt += n / p;n /= p;}return cnt;
}//高精乘模拟(压位优化,四位)
void mul(int *vec, int x) {int t = 0;for (int i = 1; i <= vec[0]; ++i) {vec[i] = vec[i] * x + t;t = vec[i] / 10000;vec[i] %= 10000;}while (t) {vec[++vec[0]] = t % 10000;t /= 10000;}return ;
}int main() {int n;scanf("%d", &n);Get_prime(n * 2);//遍历所有可能是(n*2)!的质因子,如果存在把个数存放到相应位置。之后相对位置减去n!的质因子个数for (int i = 0; i < cnt; ++i) {int ind = prime[i];nums[ind] = Get_div(n * 2, ind) - Get_div(n, ind) * 2;}//减去n+1含有的因子int x = n + 1;for (int i = 0; x > 1; ++i) {while (x > 1 && x % prime[i] == 0) {--nums[prime[i]];x /= prime[i];}}int vec[1000000] = {1, 1};for (int i = 2; i <= 2 * n; ++i) {for (int j = 1; j <= nums[i]; ++j) {mul(vec, i);}}//第一位不需要补前导0printf("%d", vec[vec[0]]);for (int i = vec[0] - 1; i > 0; --i) {printf("%04d", vec[i]);}putchar('\n');return 0;
}

Catalan (卡特兰数)相关推荐

  1. 【数论】——Catalan 卡特兰数

    Catalan 卡特兰数 文章目录 Catalan 卡特兰数 定义 计算 证明 推论 代码 定义 给定 n 个 0 和 n 个 ** 1**,它们将按照某种顺序排成长度为 **2n ** 的序列,求它 ...

  2. [杂谈] 14. Catalan卡特兰数

    文章目录 1. 前言 2. 卡特兰数递推公式推导 3. 卡特兰数性质 4. 卡特兰数简单实例 实例1:进出栈问题 实例2:进出栈问题变种 实例三:电影购票问题 实例四:上班路径问题 实例五:乘法结合律 ...

  3. 关于Catalan(卡特兰)数的理解

    卡特兰数的起源 Catalan数源自Euler对凸多边形通过不相交的对角线切分成三角形的不同切分方案数. n+1个顶点(A1,A2...An+1)的凸多边形,取定多边形的一条边,不妨设为A1An+1, ...

  4. Catalan卡特兰数

    卡特兰数是组合数学中一个常出现在各种计数问题中的数列,其前几项为(从第零项开始) : 1, 1, 2, 5, 14, 42- 计算卡特兰数的通项公式:h(n)=C(2n,n)/(n+1) 卡特兰数的应 ...

  5. 卡特兰数 Catalan

    做初赛题,回顾到以前学的一些知识,发现还有其他广泛的应用,所以在此记录并当作复习,若有不当之处,随时欢迎读者斧正. Catalan 卡特兰数又称卡塔兰数,卡特兰数是组合数学中一个常出现在各种计数问题中 ...

  6. Catalan数——卡特兰数

    今天阿里淘宝笔试中碰到两道组合数学题,感觉非常亲切,但是笔试中失踪推导不出来 后来查了下,原来是Catalan数.悲剧啊,现在整理一下 Catalan数--卡特兰数] 一.Catalan数的定义令h( ...

  7. C++打印0到N的Catalan数卡特兰数(附完整源码)

    打印0到N的Catalan数卡特兰数 打印0到N的Catalan数卡特兰数算法的完整源码(定义,实现,main函数测试) 打印0到N的Catalan数卡特兰数算法的完整源码(定义,实现,main函数测 ...

  8. 程序员数学--卡特兰数(Catalan number)

    10个高矮不同的人,排成两排,每排必须是从矮到高排列,而且第二排比对应的第一排的人高,问有多少种排列方式? 我们可以先把这10个人从低到高排列,然后,选择5个人排在第一排,那么剩下的5个人肯定是在第二 ...

  9. 卡特兰数Catalan number的应用

    卡特兰数(Catalan number)的应用 使用场景 计算公式   卡特兰数是一个特殊的数列,基于这个数列,可以找出很多有趣的问题,对于我们学计算机的而言,与这个数列打交道是不可避免了,举一个很经 ...

最新文章

  1. 计算机基础在小学的教学论文,小学基础教育论文范文
  2. react-router中离开确认组件Prompt
  3. Linux 热插拔(Hot Plug)处理机制系列
  4. KL-divergence
  5. 如何在Office 2007中查看关于对话框和版本信息
  6. abp vue如何配置服务地址_DHCP服务如何配置才能尽量减少被攻击的可能
  7. 2016年全国计算机技术与软件,2016年的上半年的全国计算机技术与软件专业技术资格(水平)考.doc...
  8. 飞桨PaddleHub实现皮影戏
  9. HDU - 4456 Crowd
  10. 成年人的世界,嘴上喊的都是主义,心里装的都是生意
  11. SQL基础(一):SQL语法和命令
  12. jni回调java类中函数_Andriod JNI编程之C++回调Java函数
  13. 情侣推送早安问候之小程序订阅通知模板推送 (出现在消息列表的服务通知)
  14. wⅰndows错误恢复,Windows错误恢复怎么办详细解决
  15. PHP更换网页背景,更换网页的背景图
  16. 腾讯云播放器隐藏音频播放的按钮
  17. envi5.6处理gf3(SAR)详细过程记录
  18. [数据科学] 通过基因表达监测进行肿瘤预测
  19. html怎么设置点击播放音乐,html5点击播放音乐试听按钮动画特效
  20. 7、公共电话交换网络(物理层)

热门文章

  1. HDU 3518 HDU 4416【后缀自动机len的使用】
  2. matlab 画图基本介绍
  3. 学计算机会不会老年痴呆,久玩电脑会得老年痴呆吗
  4. 深度学习基础笔记——前向传播与反向传播
  5. 如何展示舞台灯光秀的艺术表现力
  6. 【promise】什么是promise?
  7. kettle定时备份->mysql+mongoDB增量备份
  8. 【量化】股市技术分析利器之TA-Lib(二)
  9. 关于如何在idea中设置文档注释模板
  10. 【Raw use of parameterized class ‘xxx‘ 】