卡特兰数

卡特兰数

优秀博客

1

2

3

卡特兰数是一种经典的组合数,经常出现在各种计算中,其前几项为 : 1, 2, 5, 14, 42,132, 429, 1430, 4862, 16796,

如果打表or手模找到如上规律可考虑卡特兰数

公式1:

\(Catalan(n)=\sum_{i=0}^{n-1}{Catalan(i)*Catalan(n-i-1)}\)

进出栈问题

模板

QUESTION : 一个足够大的栈的进栈序列为1,2,3,⋯,n时有多少个不同的出栈序列?

f[i]表示i个数的全部可能性。

f[0] = 1, f[1] = 1; 设 x 为当前出栈序列的最后一个,则x有n种取值

由于x是最后一个出栈的,所以可以将已经出栈的数分成两部分

  1. 比x小 2.比x大

比x小的数有x-1个,所以这些数的全部出栈可能为f[x-1]

比x大的数有n-x个,所以这些数的全部出栈可能为f[n-x]

这两部分互相影响,所以一个x的取值能够得到的所有可能性为f[x-1] * f[n-x]

另外,由于x有n个取值,所以

公式2:

\(ans = f[0]*f[n-1] + f[1]*f[n-2] + ... + f[n-1]*f[0];\)

同理解释公式1 :考虑最后一个出栈的元素,比其先进栈先出栈的元素有i个,则比其后进栈先出栈的元素有n−i−1

球迷购票问题

双倍经验

法1:dp

必须先有 50 元,才能收 100 元(每收一个 100 就得找出一个 50),所以我们枚举手头 50 元的张数就行了。

$ dp[ i ][ j ] $表示考虑到了前 i 个人,手里现有 j 张 50 。(0<=j<=i)

每一个$ dp[ i ][ j ] $可以由上一个拿了 50 或者 100 转移过来。

拿了 100 就是 $ dp[i-1][j-1] $,(拿了 100 自然就得找出一张 50,所以是 j-1)那拿了 50 就自然是 $ dp[i-1][j+1] $了(手头多了一张 50)

#include <cstdio>
#include <iostream>
using namespace std;
long long f[5050][50];
int n;
int main(){
    scanf("%d",&n);
    f[0][0]=1;
    for(int i=1;i<=n*2;i++)
        for(int j=0;j<=min(i,n);j++){
            if(j-1>=0)f[i][j]+=f[i-1][j-1];
            if(j+1<=i+1)f[i][j]+=f[i-1][j+1];
        }   
    printf("%lld\n",f[n+n][0]);
    return 0;
}

法2:

一个A买票后售票处会积累50元钱,一个B买票需要售票处找零50元钱

说明在一个B买票前至少需要一个A买过票,那么我们就可以将A看作左括号,B看作右括号

问题就是要求合法得括号匹配,即Catalan数

n得范围开long long不会溢出 所以用一个快一些的递推公式

$ h(n)=h(n−1)∗(4∗n−2)/(n+1) $

cat[0]=cat[1]=1;
for(int i=2;i<=n;++i)
	cat[i]=cat[i-1]*(4*i-2)/(i+1);

方格问题

在n*n的格子中,只在下三角行走,每次横或竖走一格,有多少中走法?

其实向右走相当于进栈,向左走相当于出栈,本质就是n个数出栈次序的问题,所以答案就是卡特兰数。

二叉搜索树问题

**QUESTION ** 有n个结点,问总共能构成几种不同的二叉树

如果采用中序遍历的话,根结点第k个被访问到,则根结点的左子树有k-1个点、根结点的右指数有n-k个点。k的取值范围为1到n,公式1显然可推

**QUESTION ** 有n+1个叶子的满二叉树的个数?

向左记为+1,向右记为−1,按照向左优先的原则,从根节点开始遍历.例如第一个图记为+1,+1,+1,−1,−1,−1,于是由卡特兰数的含义可得满二叉树的个数为Cn

凸多边形的三角形划分问题

**QUESTION ** 一个凸的n边形,用直线连接他的两个顶点使之分成多个三角形,每条直线不能相交,问一共有多少种划分方案。

选择一个基边,显然这是多边形划分完之后某个三角形的一条边。图中我们假设基边是p1pn,我们就可以用p1、pn和另外一个点假设为pi做一个三角形,并将多边形分成三部分,除了中间的三角形之外,一边是i边形,另一边是n-i+1边形。i的取值范围是2到n-1。所以本题的解c(n)=c(2)c(n-1)+c(3)c(n-2)+…c(n-1)c(2)。令t(i)=c(i+2)。则t(i)=t(0)t(i-1)+t(1)t(i-2)…+t(i-1)t(0)

posted @ 2020-08-22 19:31  ke_xin  阅读(34)  评论(0编辑  收藏  举报