AcWing 415:栈 ← 卡特兰数

【题目来源】
https://www.acwing.com/problem/content/417/
https://www.luogu.com.cn/problem/P1044

【题目描述】
栈是计算机中经典的数据结构,简单的说,栈就是限制在一端进行插入删除操作的线性表。
栈有两种最重要的操作,即 pop(从栈顶弹出一个元素)和 push(将一个元素进栈)。 
栈的重要性不言自明,任何一门数据结构的课程都会介绍栈。
宁宁同学在复习栈的基本概念时,想到了一个书上没有讲过的问题,而他自己无法给出答案,所以需要你的帮忙。
宁宁考虑的是这样一个问题:一个操作数序列,从 1,2,一直到 n,栈 A 的深度大于 n。 现在可以进行两种操作: 
(1)将一个数,从操作数序列的头端移到栈的头端(对应数据结构栈的 push 操作)。
(2)将一个数,从栈的头端移到输出序列的尾端(对应数据结构栈的 pop 操作)。
使用这两种操作,由一个操作数序列就可以得到一系列的输出序列。
你的程序将对给定的 n,计算并输出由操作数序列 1,2,…,n 经过以上两种操作可能得到的输出序列的总数。

【输入格式】
输入文件只含一个整数 n。

【输出格式】
输出文件只有一行,即可能输出序列的总数目。

【数据范围】
1≤n≤18

【输入样例】
3

【输出样例】
5

【算法分析】
● 卡特兰数(Catalan number)是组合数学中一个常出现在各种计数问题中的数列。若
从第 0 项开始,则卡特兰数列 h[n] 为:1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440, 9694845, 35357670, 129644790, …。

● 常用的卡特兰数列 h[n] 有如下 4 种等价的递推式

h[n]=h[0]*h[n−1]+h[1]*h[n−2]+...+h[n−1]*h[0], (n≥2, h[0]=h[1]=1)
h[n]=h[n−1]*(4*n−2)/(n+1), (n≥2, h[0]=h[1]=1)
h[n]=C(2n,n)−C(2n,n−1), (n=0,1,2,...)
h[n]=C(2n,n)/(n+1), (n=0,1,2,...)

● 卡特兰数的第 20 项为 6564120420,大于 2×10^9,所以代码中要声明为
long long 型。

● n
个元素进栈/出栈合法序列的个数 = 第 n 个卡特兰数
第一个出栈元素为第 ‌k+1‌ 个进栈元素时,前 k 个元素的合法出栈序列数为 h[k],剩余 n−k−1 个元素的合法出栈序列数为 h[n-k-1]。(0 ≤ k ≤ n-1
由于 k 可以从 0 取到 n-1,根据乘法原理和加法原理,可得递推关系
h[n]=h[0]*h[n−1]+h[1]*h[n−2]+...+h[n−1]*h[0], (n≥2, h[0]=h[1]=1)。这个递推关系就是卡特兰数的递推式。

【算法代码】

#include 
using namespace std;
 
typedef long long LL;
const int maxn=1e5+5;
LL h[maxn];
LL n;
 
int main() {
    scanf("%lld",&n);
    h[0]=1,h[1]=1;
    for(int i=2; i<=n; i++) {
        h[i]=h[i-1]*(4*i-2)/(i+1);
    }
    printf("%lld",h[n]);
 
    return 0;
}
 
/*
in:3
out:5
*/






【参考文献】
https://blog.csdn.net/hnjzsyjyj/article/details/147968680
https://blog.csdn.net/hnjzsyjyj/article/details/145842440
https://blog.csdn.net/hnjzsyjyj/article/details/137119444
https://blog.csdn.net/hnjzsyjyj/article/details/148775674






 

你可能感兴趣的:(信息学竞赛,#,算法数学基础,卡特兰数)