码迷,mamicode.com
首页 > 其他好文 > 详细

浅谈“卡特兰数”

时间:2018-10-29 16:01:01      阅读:207      评论:0      收藏:0      [点我收藏+]

标签:namespace   span   浅谈   数组   不同的   个数   blank   pre   scanf   

引入:卡特兰数。

卡特兰数又称卡塔兰数,英文名Catalan number,是组合数学中一个常出现在各种计数问题中出现的数列。

——百度百科


一:运算公式。

令h(0)=1,h(1)=1,catalan数满足递推式 :
h(n)= h(0)*h(n-1)+h(1)*h(n-2) + ... + h(n-1)*h(0) (n>=2)
 
例如:
h(3)=h(0)*h(2)+h(1)*h(1)+h(2)*h(0)=1*2+1*1+2*1=5

二:代码实现。

#include <bits/stdc++.h>
int n, f[30];
int main()
{
    scanf("%d",&n);
    f[0]=1,f[1]=1;
    for(int i=2; i<=n; i++)              
        for(int j=0; j<i; j++) 
            f[i]+=f[j]*f[i-j-1]; //卡特兰数 
    printf("%d",f[n]);
    return 0;
}

这里用了递推的算法。

还可以用递归实现:

#include<bits/stdc++.h>
using namespace std;
int h(int n)
{
if(n==0||n==1) return 1; return h(n-1)*(4*n-2)/(n+1);//公式 } int main(){ int n; cin>>n; cout<<h(n); return 0; }

 


三:应用。

·题目描述

  Luogu P1044 栈 [原题链接]

·解析

本题的描述十分简单。n个数依次进栈,可随机出栈。求有几种可能。

DFS是可以解的,但仔细思考思考,就会发现一个更简单的方法。

我们不妨建立数组f。f[i]表示i个数进出的全部可能性。

那么f[0] = 1, f[1] = 1;(0个数或1个数也没什么其他可能了。)

若设 x 为当前出栈序列的最后一个,则x有n种取值

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

  • 比x小
  • 比x大

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

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

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

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

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

显而易见——卡特兰数

题目的数据范围很小,所以直接贴模板也是可以过的。


四:总结。

那么,就先这样吧。
其实Catalan数还有以下用法:
  • 括号化 矩阵连乘: P=a1×a2×a3×……×an,依据乘法结合律,不改变其顺序,只用括号表示成对的乘积,试问有几种括号化的方案?(h(n)种)
  • 给定节点组成二叉搜索树:给定N个节点,能构成多少种不同的二叉搜索树?(能构成h(N)个)(这个公式的下标是从h(0)=1开始的)

n对括号正确匹配数目:给定n对括号,求括号正确配对的字符串数。(h(n)种)

·经典必练

  P1722 矩阵 II [原题链接]

 

浅谈“卡特兰数”

标签:namespace   span   浅谈   数组   不同的   个数   blank   pre   scanf   

原文地址:https://www.cnblogs.com/-Wallace-/p/9869758.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!