卡特兰数

来源:互联网 发布:淘宝哪家二手单反店好 编辑:程序博客网 时间:2024/04/28 23:18

How Many Trees?


题意:给定一棵n个节点的二叉树, 求这棵树有多少个二叉树。


数据范围: n<=100


思路

n个节点的二叉树有多种,多种二叉树里面又有子树。当n到达100时,结果是一个庞大的数字,所以要用到大数。

在卡特兰数的应用里面,求二叉树的个数是一个典型的应用,还有 合法的入栈出栈序列数、多边形分成三角形的个数、圆括弧插入公式中的方法数  都是卡特兰数的应用


卡特兰数详解: Math173   (这个版面好看)


代码

#include <stdio.h>     //最大到100,进行预处理#include <iostream>#include <string.h>#define base 10000#define maxn 100 using namespace std;int num[105][100];void multiply(int a[],int b){int i,temp = 0;for(i = maxn - 1; i >= 0; i--){temp += a[i]*b;a[i] = temp%base;temp /= base;}}void dive(int a[],int b){int i,temp = 0;for(i = 0; i < maxn; i++){temp = temp*base + a[i];a[i] = temp / b;temp %= b;}}int main(){int i,n;memset(num,0,sizeof(num));num[1][maxn-1] = 1;for(i = 2; i <= 100;i++){memcpy(num[i],num[i-1],maxn*sizeof(int));multiply(num[i],4*i-2);dive(num[i],i+1);}while(scanf("%d",&n)!=EOF){i = 0;while(num[n][i] == 0)i++;printf("%d",num[n][i++]);for(; i < maxn; i++){printf("%04d",num[n][i]);}printf("\n");}return 0;}


以上等价于求 n个入栈操作,n个出栈操作,典型的入栈操作数 等于 出栈操作数,但是还有不等于的情况,如下:


Buy the Ticket


题意:电影院卖票。一张票50元。一开始没有零钱。有m+n个人买票,m个人拿50元的钞票,n个人拿100的。问队伍有多少种排列方式可以使得卖票能顺利进行下去。


数据范围:m, n <=100 , m==n==0结束输入


题解:很典型的卡特兰数,详情参见  i_fuqiang的专栏  


代码

#include <iostream>#include <string>using namespace std;#define MAX 100#define BASE 10000void multiply(int a[],int Max,int b)  //大数乘小数{    int i,array=0;    for (i=Max-1; i>=0; i--)       {        array+=b*a[i];        a[i] = array%BASE;        array /= BASE;       }}void divide(int a[], int Max, int b)  //大数除小数{    int i,div=0;    for (i=0;i<Max; i++)       {        div = div*BASE + a[i];        a[i] = div / b;        div %= b;    }}int fact[205][MAX];void setFact ()  //求出0-200的阶乘值 {     fact[0][MAX-1] = fact[1][MAX-1] = 1;     for ( int i = 2; i <= 200; ++ i )     {           memcpy ( fact[i] , fact[i-1] , MAX * sizeof ( int ) );           multiply ( fact[i] , MAX , i );      } }void outPut ( int ctl[MAX] ){     int i = 0;     while ( i < MAX && ctl[i] == 0 )//去掉前面的为0的项      {             i ++ ;      }     printf ( "%d", ctl[i++] );                  while ( i < MAX )        {             printf ( "%04d", ctl[i++] );        }      putchar ( '\n' ); }int res[MAX];int main (){     int M,N;     int ca = 1;     setFact();  //打表      while ( cin >> M >> N , M + N )     {             printf ( "Test #%d:\n",ca++ );             if ( N > M )             {                  puts ( "0" );                  continue;              }             memcpy ( res , fact[M+N] , MAX * sizeof ( int ) ); //阶乘 ( m + n )!             multiply ( res, MAX, M - N + 1 );    // ( m + n )! * ( m-n+1 )             divide ( res, MAX, M + 1 );   // ( m + n )! * ( m-n+1 )  / ( m+ 1 )                      outPut ( res );     }     return 0;}