问题描述:
This is a small but ancient game. You are supposed to write down the numbers 1, 2, 3, ... , 2n - 1, 2n consecutively in clockwise order on the ground to form a circle, and then, to draw some straight line segments to connect them into number pairs. Every number must be connected to exactly one another. And, no two segments are allowed to intersect.
It's still a simple game, isn't it? But after you've written down the 2n numbers, can you tell me in how many different ways can you connect the numbers into pairs? Life is harder, right?
输入:
Each line of the input file will be a single positive number n, except the last line, which is a number -1. You may assume that 1 <= n <= 100.
输出:
For each n, print in a single line the number of ways to connect the 2n numbers into pairs.
样本输入:
2
3
-1
样本输出:
2
5
问题讲解:
卡特兰数又称卡塔兰数,英文名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(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,...)
代码:
#include<iostream>
using namespace std;
const int size=101;//表示数组存放的数据的长度
int main()
{
int i,j,r,temp,len;
int a[101][size]={0};
r=0;len=1;a[1][0]=1;//len表示有效长度,r表示进位,初始化a[1][0]=1,表示n-1时,值为1
//公式为h(n)=h(n-1)*(4*n-2)/(n+1); 先进行大数的乘法运算 是从低位开始,在进行除法运算,从高位开始
for(i=2;i<=100;i++)
{
for(j=0;j<len;j++)//表示从低位开始
{
a[i][j]=a[i-1][j]*(4*i-2);
}
for(j=0;j<len;j++)
{
temp=a[i][j]+r;
a[i][j]=temp%10;//这样保证一位数占用数组的一位,但注意,len其实并不能包含高位
r=temp/10;
}
while(r)//开始对高位进行处理
{
a[i][len]=r%10;
r=r/10;
len++;
}
//开始大数除法运算 是从高位开始
for(j=len-1,r=0;j>=0;j--)
{
temp=r*10+a[i][j];
a[i][j]=temp/(i+1);
r=temp%(i+1);
}
//还要求有效位数
while(!a[i][len-1])
{
len--;//为了求有效位数 为下一次的递推做准备
}
}
int n;
while(cin>>n && n!=-1)
{
for(i=size-1;!a[n][i];i--);//这里是为了确定有效位数
for(i;i>=0;i--)
cout<<a[n][i];//输出时 从高位依次输出
cout<<endl;
}
return 0;
}