# Train Problem II（卡特兰数以及高精度运算）

 Problem Description As we all know the Train Problem I, the boss of the Ignatius Train Station want to know if all the trains come in strict-increasing order, how many orders that all the trains can get out of the railway. Input The input contains several test cases. Each test cases consists of a number N(1<=N<=100). The input is terminated by the end of file. Output             For each test case, you should output how many ways that all the trains can get out of the railway. Sample Input 1 2 3 10 Sample Output 1 2 5 16796
Hint The result will be very large, so you may not process it by 32-bit integers. Author Ignatius.L

Catalan数的组合公式为 Cn=C(2n,n) / (n+1);

#include<iostream>
using namespace std;
int a[101][101]={0};
int main()
{
int n,i,j,len,r,temp,t;
int b[101];
a[1][0] = 1;
len = 1;
b[1] = 1;
for(i=2;i<=100;i++)
{
t = i-1;
for(j=0;j<len;j++) //乘法
a[i][j] = a[i-1][j]*(4*t+2);
for(r=j=0;j<len;j++)  //处理相乘结果
{
temp = a[i][j] + r;
a[i][j] = temp % 10;
r = temp / 10;
}
while(r) //进位处理
{
a[i][len++] = r % 10;
r /= 10;
}

for(j=len-1,r=0;j>=0;j--) //除法
{
temp = r*10 + a[i][j];
a[i][j] = temp/(t+2);
r = temp%(t+2);
}
while(!a[i][len-1]) //高位零处理
len --;
b[i] = len;
}
while(cin>>n)
{
for(j=b[n]-1;j>=0;j--)
printf("%d",a[n][j]);
printf("/n");
}
return 0;
}  

//输出卡特兰数
//首先需要肯定，程序是正确的
//这算是大数乘除法！记住他们是如何处理的！由于数据很大，用基本数据类型根本无法满足要求，只能用数组来表示！
#include <iostream>
#include<cstdio>
#include<memory.h>
using namespace std;
#define MAX 101
#define BASE 10000//base只是一个基度，对最终取值并没有影响，相反，base取值愈大，计算量愈小
//base发生改变的时候，下面的输出也要相应地做出调整，否则也会输出错误答案！除非当base取10！
void multiply(int a[],int len,int b)//乘法
{
for(int i=len-1,carry=0;i>=0;--i)//从最后一位开始相乘,依次向前与每一位相乘
{//问题在于，为什么BASE=10000？
carry+=b*a[i];
a[i]=carry%BASE;
carry/=BASE;
}
}
void divide(int a[],int len,int b)//除法，很妙的！这种除法可能想不到，仔细体会！
{//应当如何除呢？
for(int i=0,div=0;i<len;++i)//从高位除起
{
div=div*BASE+a[i];
a[i]=div/b;//b为除数
div%=b;
}
}
int main()
{
int i,j,h[101][MAX];
memset(h[1],0,MAX*sizeof(int));//赋值，每一个都置为0
for(i=2,h[1][MAX-1]=1;i<=100;++i)//运用递归，并且h[1]=1;
{
memcpy(h[i],h[i-1],MAX*sizeof(int));//h[i]=h[i-1];按字节拷贝，保证了h[i]和h[i-1]指向数组的一致性
multiply(h[i],MAX,4*i-2);//h[i]*=(4*i-2);
divide(h[i],MAX,i+1);//h[i]/=(i+1);
}//递归得到前100项的卡特兰数！
while(cin>>i && i>=1 && i<=100)//输入i的值
{

for(j=0;j<MAX && h[i][j]==0;++j);//从0位开始搜索，找到不为0的第一个数
//在c语言中，EOF=-1；
printf("%d",h[i][j++]);//像是这个输出，就很妙了，第一位可能不足四位，就地输出！
for(;j<MAX;++j)
{
printf("%04d",h[i][j]);//处在中间的值也可能没有四位，这时候要注意了，往左边加0，凑足4位，不然答案会出错！

}

printf("\n");
}
//system("pause");

return 0;
}


//ｈ( n ) = ( ( 4*n-2 )/( n+1 )*h( n-1 ) );

#include<stdio.h>

//*******************************
//打表卡特兰数
//第 n个 卡特兰数存在a[n]中，a[n][0]表示长度；
//注意数是倒着存的，个位是 a[n][1] 输出时注意倒过来。
//*********************************
int a[105][100];
void ktl()
{
int i,j,yu,len;
a[2][0]=1;
a[2][1]=2;
a[1][0]=1;
a[1][1]=1;
len=1;
for(i=3;i<101;i++)
{
yu=0;
for(j=1;j<=len;j++)
{
int t=(a[i-1][j])*(4*i-2)+yu;
yu=t/10;
a[i][j]=t%10;
}
while(yu)
{
a[i][++len]=yu%10;
yu/=10;
}
for(j=len;j>=1;j--)
{
int t=a[i][j]+yu*10;
a[i][j]=t/(i+1);
yu = t%(i+1);
}
while(!a[i][len])
{
len--;
}
a[i][0]=len;
}

}
int main()
{
ktl();
int n;
while(scanf("%d",&n)!=EOF)
{
for(int i=a[n][0];i>0;i--)
{
printf("%d",a[n][i]);
}
puts("");
}
return 0;
}