Catalan (卡特兰数)
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=AmmAnm=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−1f(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⌊logpN⌋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 (卡特兰数)相关推荐
- 【数论】——Catalan 卡特兰数
Catalan 卡特兰数 文章目录 Catalan 卡特兰数 定义 计算 证明 推论 代码 定义 给定 n 个 0 和 n 个 ** 1**,它们将按照某种顺序排成长度为 **2n ** 的序列,求它 ...
- [杂谈] 14. Catalan卡特兰数
文章目录 1. 前言 2. 卡特兰数递推公式推导 3. 卡特兰数性质 4. 卡特兰数简单实例 实例1:进出栈问题 实例2:进出栈问题变种 实例三:电影购票问题 实例四:上班路径问题 实例五:乘法结合律 ...
- 关于Catalan(卡特兰)数的理解
卡特兰数的起源 Catalan数源自Euler对凸多边形通过不相交的对角线切分成三角形的不同切分方案数. n+1个顶点(A1,A2...An+1)的凸多边形,取定多边形的一条边,不妨设为A1An+1, ...
- Catalan卡特兰数
卡特兰数是组合数学中一个常出现在各种计数问题中的数列,其前几项为(从第零项开始) : 1, 1, 2, 5, 14, 42- 计算卡特兰数的通项公式:h(n)=C(2n,n)/(n+1) 卡特兰数的应 ...
- 卡特兰数 Catalan
做初赛题,回顾到以前学的一些知识,发现还有其他广泛的应用,所以在此记录并当作复习,若有不当之处,随时欢迎读者斧正. Catalan 卡特兰数又称卡塔兰数,卡特兰数是组合数学中一个常出现在各种计数问题中 ...
- Catalan数——卡特兰数
今天阿里淘宝笔试中碰到两道组合数学题,感觉非常亲切,但是笔试中失踪推导不出来 后来查了下,原来是Catalan数.悲剧啊,现在整理一下 Catalan数--卡特兰数] 一.Catalan数的定义令h( ...
- C++打印0到N的Catalan数卡特兰数(附完整源码)
打印0到N的Catalan数卡特兰数 打印0到N的Catalan数卡特兰数算法的完整源码(定义,实现,main函数测试) 打印0到N的Catalan数卡特兰数算法的完整源码(定义,实现,main函数测 ...
- 程序员数学--卡特兰数(Catalan number)
10个高矮不同的人,排成两排,每排必须是从矮到高排列,而且第二排比对应的第一排的人高,问有多少种排列方式? 我们可以先把这10个人从低到高排列,然后,选择5个人排在第一排,那么剩下的5个人肯定是在第二 ...
- 卡特兰数Catalan number的应用
卡特兰数(Catalan number)的应用 使用场景 计算公式 卡特兰数是一个特殊的数列,基于这个数列,可以找出很多有趣的问题,对于我们学计算机的而言,与这个数列打交道是不可避免了,举一个很经 ...
最新文章
- 计算机基础在小学的教学论文,小学基础教育论文范文
- react-router中离开确认组件Prompt
- Linux 热插拔(Hot Plug)处理机制系列
- KL-divergence
- 如何在Office 2007中查看关于对话框和版本信息
- abp vue如何配置服务地址_DHCP服务如何配置才能尽量减少被攻击的可能
- 2016年全国计算机技术与软件,2016年的上半年的全国计算机技术与软件专业技术资格(水平)考.doc...
- 飞桨PaddleHub实现皮影戏
- HDU - 4456 Crowd
- 成年人的世界,嘴上喊的都是主义,心里装的都是生意
- SQL基础(一):SQL语法和命令
- jni回调java类中函数_Andriod JNI编程之C++回调Java函数
- 情侣推送早安问候之小程序订阅通知模板推送 (出现在消息列表的服务通知)
- wⅰndows错误恢复,Windows错误恢复怎么办详细解决
- PHP更换网页背景,更换网页的背景图
- 腾讯云播放器隐藏音频播放的按钮
- envi5.6处理gf3(SAR)详细过程记录
- [数据科学] 通过基因表达监测进行肿瘤预测
- html怎么设置点击播放音乐,html5点击播放音乐试听按钮动画特效
- 7、公共电话交换网络(物理层)