卡特兰数 应用

卡特兰数真是一个神奇的数字,很多组合问题的数量都和它有关系,例如:

  • Cn= 长度为 2n的 Dyck words的数量。 Dyck words是由 n个 X和 n个 Y组成的字符串,并且从左往右数, Y的数量不超过 X,例如长度为 6的 Dyck words为:

XXXYYY XYXXYY XYXYXY XXYYXY XXYXYY

  • Cn= n对括号正确匹配组成的字符串数,例如 3对括号能够组成:

((())) ()(()) ()()() (())() (()())

  • Cn= n+1个数相乘,所有的括号方案数。例如, 4个数相乘的括号方案为:

 
((ab)c)d (a(bc))d (ab)(cd) a((bc)d) a(b(cd))

  • Cn= 拥有 n+1 个叶子节点的二叉树的数量。例如 4个叶子节点的所有二叉树形态:

Catalan number binary tree example.png

  • Cn=n*n的方格地图中,从一个角到另外一个角,不跨越对角线的路径数,例如, 4×4方格地图中的路径有:

Catalan number 4x4 grid example.svg

  • Cn= n+2条边的多边形,能被分割成三角形的方案数,例如 6边型的分割方案有:

Catalan-Hexagons-example.svg

  • Cn= 圆桌周围有 2n个人,他们两两握手,但没有交叉的方案数。

引用:http://blog.163.com/kevinlee_2010/blog/static/169820820201010894212352/

求一个数的卡塔兰数

使用递推式 H(n) = c(2n,n)/n+1;

改写为A(2n,n)/ (n+1)!

使用大数相乘相除计算

#include <cstdio>
#include <iostream>
#include <cstring>

using namespace std;

#define N 250
int a[N];

void init(int n)
{
    memset(a,0,sizeof(a));
    a[0] = 1;
    int i = 0;
    int j = 0;
    int k1 = 1;
    for(i = 2*n; k1 <= n; i--,k1++)
      {
          int t = 0;
          int mul = 0;
          for(j = 0; j <= N; j++)
            {
               mul = a[j] *i + t;
               a[j] = mul % 10;
               t = mul / 10;
            }
      }

    for(i = 2; i <= n+1; i++)
        {
            int t1 = 0;
            int mul1 = 0;
            for(j = N; j >= 0;j--)
                {
                    mul1 = mul1 *10 + a[j];
                    a[j] = mul1 / i;
                    mul1 %= i;
                }
        }

  int k = N;
  while(k--)
   if(a[k])
     break;
    k += 1;
    while(k--)
      printf("%d",a[k]);
      printf("\n");
}

int main()
{
    int n;
    while(scanf("%d",&n) != EOF)
     {
         if(n < 2)
           printf("%d\n",1);
        else
         init(n);
     }
    return 0;
}

原文地址:https://www.cnblogs.com/yyroom/p/3035955.html