卡特兰数(Catalan)及应用

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

令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(2)=h(0)*h(1)+h(1)*h(0)=1*1+1*1=2
h(3)=h(0)*h(2)+h(1)*h(1)+h(2)*h(0)=1*2+1*1+2*1=5
另类递推式:
h(n)=h(n-1)*(4*n-2)/(n+1);
递推关系的解为:
h(n)=C(2n,n)/(n+1) (n=0,1,2,...)
递推关系的另类解为:
h(n)=c(2n,n)-c(2n,n+1)(n=0,1,2,...)
n=100
       896519947090131496687170070074100632420837521538745909320
实例应用

1)P=a1*a2*a3*...*an 加括号改变乘积顺序的个数是卡特兰数。

2) 一个栈的进栈序列为1,2,...n,则合法的出栈序列的个数为h(n+1)=C(n,2n)/(n+1).理解:把进栈状态设为1,      出栈设为0,进栈的数目必须大于出栈的数目。输出序列的总数目=自左向右扫描由n个1和n个0组成的2n位二进      制数,相当于1的累计计数不小于0的累计计数的方法数。

3)有n个叶子的完全二叉树的个数为h(n),等价于问题1).

4)排队找零问题:入场费5元,有2n个人,其中n个人有5元零钱,n个人只有10元钱,要求排队序列可以找开零钱。      等价于问题2):把5元的状态视为1,10元的视为0,仍是要求自左向右的01序列中1的个数大于0的个数

5)凸多边形划分:在凸n边形中,通过插入内部不相交的对角线将其分成若干三角形区域,划分数为h(n-1) (        n>=4).

6) 从点(0,0)到点(n,n)的除端点外不能接触直线y=x的 路径数目为 2h(n),2倍是因为对称。


题目  多会用到大数运算
分析:由题意
h(2)=h(0)*h(1)+h(1)*h(0)=1*1+1*1=2
h(3)=h(0)*h(2)+h(1)*h(1)+h(2)*h(0)=1*2+1*1+2*1=5
//1134 卡特兰数 h(n)=h(n-1)*(4*n-2)/(n+1); 
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define N 100
#define M 10000//以4位为单位 
int h[101][N]={0};//n最大要等于100,101处不要写成100 数据存放为最高位靠近数组下标为0处
void multi(int n){//大数与一个int型数相乘 
	int m=4*n-2,tem,carry=0;
	for(int i=N-1;i>=0;i--){
		tem=h[n-1][i]*m+carry;
		carry=tem/M;
		h[n][i]=tem%M;
		//printf("h[%d][%d]=%d  ",n,i,h[n][i]);
	} 
} 
void div(int n){
	int m=n+1,tem,mod=0;
	for(int i=0;i<=N-1;i++){
		int t=mod*M+h[n][i];
		tem=(t)/m; 
		mod=t%m;
		h[n][i]=tem;
		//printf("h[%d][%d]=%d  ",n,i,h[n][i]);
	} 
}
void catalan(){
	memset(h[1],0,sizeof(h[1]));
	h[1][N-1]=1;
	for(int i=2;i<101;i++){
		multi(i);
		div(i);
	}
}
int main(){
	int n;
	catalan();
	while(scanf("%d",&n)!=EOF&&n!=-1){
		int i=0;
		while(h[n][i]==0){
			i++;
		}
		printf("%d",h[n][i++]); 
		for(;i<=N-1;i++){
			printf("%04d",h[n][i]);
		}
		printf("\n");
	}
	return 0;
}
 

hdu1023    hdu1130

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值