Train Problem II(Catalan数的应用以及大数的乘除法)

Train Problem II



      点我找原题
题目大意就是一个火车进站的问题,一堆火车以严格的顺序到一个站里,问出来的时候有多少种顺序。
?质上都是递推等式的应用
?卡特兰数的生成其实可以看做出栈次序。
?一个栈(无穷大)的进栈序列为123n,有多少个不同的出栈序列?
?这个问题问的是n个元素的进栈顺序一定,每种元素进栈一次出栈一次,出栈顺序有多少种,根据栈的性质,
当前出栈的元素肯定是上一个入栈的元素。
?例如  当n=4
?1 2 进栈,此时可以2出栈,变成1,还剩3,4没有进栈,如果接下来,3,4,进栈,那么接下来的出栈是,4,3,1
?即出栈顺序是2,4,3,1
?对于这类问题,我们需要把它的大问题分割成小问题,通过递归的思路解决。
? 对于每一种出栈顺序,必定有一个第一个出栈的元素,假设是第 k 个元素。
? 只要 k 不同,那么出栈顺序必定不同。
? k 元素之前有 k-1 个元素已进栈,需要出栈。
? k 元素之后又 n-k 个元素将要进栈和出栈。
? 我们用 h[n] 来表示有 n 种元素的出栈顺序,即我们最终要求得的是 h[n]
? 那么当 k=1 时,有 h[0] * h[n-1] 种方案。
? K=2 时,有 h[1]* h[n-2]
? K=n 时,有 h[n-1] * h[0]
? k 值不同的方案按照加法原理相累加。
? h(n)= h(0)*h(n-1)+h(1)*h(n-2) + ... + h(n-1)h(0 )
? 即卡特兰数的递推式,那么对于这个问题,我们求出 h[n] 即可。
? h(n)=h(n-1)*(4*n-2)/(n+1 ); 推可得。
? 卡特兰 数的思想就是把问题分割成 n 个小问题累加,找到问题的特征,即可解决问题。
以上是对catalan数推到的一个思想,接下来讲如何实现大数的乘除:
这里用一个数组来表示一个大数,例如数组a[100],那么数字是从右往左装入这个数组,一个单位装4个数字,
就是一个四位数,当然也可以是5位或6位,如过有一个数是5 4613 1546434468464867,那么a[99]= 4867; a[98]= 6846 ;
a[97]= 4344 ; a[96]= 1546 ; a[95]= 4613 ; a[94]= 5;运算乘法时是从右往左,除法是从左往右运算,最后输出时先扫出
数组前几项的0,这是要避开不输出的,然后输出第一个非零项,最后往后继续输出,每一项都输出对应的位数,
即四位数,"%04d"。这是个非常有意思的乘除法运算,要多多体会,Catalan数的推到以及应用也十分重要!




Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other)
Total Submission(s) : 36   Accepted Submission(s) : 19

Font: Times New Roman | Verdana | Georgia

Font Size:  

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.





#include
#include
#include
using namespace std;
#define MAX 100
#define BASE 10000
void 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 {
div=div*BASE+a[i];
a[i]=div/b;
div%=b;
}
}
int main(int argc, char *argv[])
{
int a[101][MAX],i,j,n;
memset(a[1],0,MAX*sizeof(int));
for(i=2,a[1][MAX-1]=1;i<101;i++)
{
memcpy(a[i],a[i-1],MAX*sizeof(int));
multiply(a[i],MAX,4*i-2);
divide(a[i],MAX,i+1);
}
while(cin>>n)
{
for(i=0;i cout< for(;i cout< }
return 0;
}



你可能感兴趣的:(组合数学题)