Train Problem II
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 6797 Accepted Submission(s): 3683
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 16796HintThe result will be very large, so you may not process it by 32-bit integers.开始看题的时候感觉挺简单,真正做起来后确实挺难,不过这道题可以说是经典中的经典。大数乘小数,大数除以小数,卡特兰数都考虑到了。写了整整一天才AC,而且自己的代码挺麻烦,所以我搜了几个大神的代码总结了一下。注释都在代码里面。
//这个代码和我的思想相同,存取方便,不过比我的简单n倍。
//C++
// h(n)=h(n-1)*(4*n-2)/(n+1)
#include <stdio.h>
// 100的卡特兰数有58位,所以(60/5)+1=13 ,不可以是12哟,每5位存一块
int cata[101][13];
void make_catalan( )
{
int i,j,jw,temp1,temp2;
cata[1][0]=cata[1][1]=1;//第0位用来存取位数,不参与数值的存取,a[1][1]则是计算数值时使用
for( i=2; i<=100; ++i )
{
// 乘法
cata[i][0]=cata[i-1][0]; //把上一个的位数复制给下一个
temp1=4*i-2;
//jw为进位
jw=0;
for( j=1; j<=cata[i][0]; ++j )
{
cata[i][j]=( cata[i-1][j]*temp1 +jw )%100000; //当前位为计算的值
jw=( cata[i-1][j]*temp1 + jw )/100000; //进位
}
if( jw!=0 ) //最后一次进位在上面的程序中没讨论
{
cata[i][j]=jw; //进位放到前面的一位上
++cata[i][0]; //位数增加
}
// 除法
temp1=temp2=0;
for( j=cata[i][0]; j>=1; --j )
{
temp2=(cata[i][j]+temp1*100000)%(i+1); //余数变为相应倍数后在进行运算
cata[i][j]= (cata[i][j]+temp1*100000) / (i+1) ; //所求的商存在原来的数位上
temp1=temp2; //余数参与下次的运算
}
// 处理高位0
if( !cata[i][ cata[i][0] ] ) //如果第一位为0,则减去一位
--cata[i][0];
}
}
int main()
{
int i,n;
make_catalan();
while( ~scanf("%d",&n) )
{
printf("%d",cata[n][ cata[n][0] ]); //输出的为最大位
// 注意非最高位要补0
for( i=cata[n][0]-1; i>=1; --i )
printf("%05d",cata[n][i]);
printf("\n");
}
return 0;
}
//以下代码不做注释
//C++
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int a[120][122];
int b[130];
int i,j,k,n;
void catalan()
{
int tem,len;
a[1][0]=1;
a[1][1]=1;
a[2][0]=1;
a[2][1]=2;
len=1;
for(i=3;i<=100;i++)
{
tem=0;
for(j=1;j<=len;j++)
{
k=a[i-1][j]*(4*i-2)+tem;
tem=k/10;
a[i][j]=k%10;
}
while(tem)
{
len++;
a[i][len]=tem%10;
tem=tem/10;
}
for(j=len;j>=1;j--)
{
k=a[i][j]+tem*10;
a[i][j]=k/(i+1);
tem=k%(i+1);
}
while(!a[i][len])
{
len--;
}
a[i][0]=len;
}
}
int main()
{
catalan();
while(scanf("%d",&n)!=EOF)
{
/*for(i=4;i<=n;i++)//h(n)=h(n-1)*(4*n-2)/(n+1);
{
//a[i]=a[i-1]*(4*i-2)/(n+1);
//printf("%lld %d\n",a[i],i);
//h[i] = h[i-1] * (4*i-2) / (i+1) ;
}
printf("%lld\n",h[n]);*/
for(i=a[n][0];i>=1;i--)
{
printf("%d",a[n][i]);
}
printf("\n");
}
return 0;
}
//C++
#include <iostream>
#include <stdio.h>
#include <cmath>
using namespace std;
int a[105][105]; //大数卡特兰数
int b[105]; //卡特兰数的长度
void catalan() //求卡特兰数
{
int i, j, len, carry, temp;
a[1][0] = b[1] = 1;
len = 1;
for(i = 2; i <= 100; i++)
{
for(j = 0; j < len; j++) //乘法
a[i][j] = a[i-1][j]*(4*(i-1)+2);
carry = 0;
for(j = 0; j < len; j++) //处理相乘结果
{
temp = a[i][j] + carry;
a[i][j] = temp % 10;
carry = temp / 10;
}
while(carry) //进位处理
{
a[i][len++] = carry % 10;
carry /= 10;
}
carry = 0;
for(j = len-1; j >= 0; j--) //除法
{
temp = carry*10 + a[i][j];
a[i][j] = temp/(i+1);
carry = temp%(i+1);
}
while(!a[i][len-1]) //高位零处理
len --;
b[i] = len;
}
}
int main()
{
int i, n;
catalan();
while(scanf("%d", &n) != EOF)
{
for(i = b[n]-1; i>=0; i--)
{
printf("%d", a[n][i]);
}
printf("\n");
}
return 0;
}
//java代码适合于对数据的处理,相对来说特别方便
public class Main
{
public static void main(String args[])
{
BigInteger[] a = new BigInteger[101];
a[0] = BigInteger.ZERO;
a[1] = BigInteger.valueOf(1);
for(int i = 2; i <= 100; ++i)
a[i] = a[i - 1].multiply(BigInteger.valueOf(4 * i - 2)).divide(BigInteger.valueOf(i+1));
Scanner in = new Scanner(System.in);
int n;
while(in.hasNext())
{
n = in.nextInt();
System.out.println(a[n]);
}
}
}