计算1-100卡特兰数,必须要用数组存,大数模板
注:
卡特兰数:卡特兰数又称卡塔兰数,是组合数学中一个常出现在各种计数问题中出现的数列。由以比利时的数学家欧仁·查理·卡塔兰 (1814–1894)命名。
原理:
令h(1)=1,h(0)=1,catalan数满足递归式: h(n)= h(0)*h(n-1)+h(1)*h(n-2) + ... +
h(n-1)h(0) (其中n>=2) 另类递归式: h(n)=((4*n-2)/(n+1))*h(n-1);
该递推关系的解为: h(n)=C(2n,n)/(n+1) (n=1,2,3,...)
卡特兰数的应用:实质上都是递归等式的应用
Description
Input
Output
Sample Input
Sample Output
Hint
The result will be very large, so you may not process it by 32-bit integers.
1 #include<iostream> 2 #include<stdio.h> 3 #include<string.h> 4 #include<math.h> 5 #include<queue> 6 #include<algorithm> 7 using namespace std; 8 int num[105][105]; 9 int b[105]; 10 void catalan() 11 { 12 int i,j,carry=0,temp=0,length; 13 num[1][0]=1;length=1;b[1]=1; 14 for(i=2;i<=100;i++) 15 { 16 for(j=0;j<length;j++)//拷贝上一组数字 17 { 18 num[i][j]=num[i-1][j]*(4*i-2); 19 } 20 carry=0; 21 for(j=0;j<length;j++)//乘法 22 { 23 temp=carry+num[i][j]; 24 num[i][j]=temp%10; 25 carry=temp/10; 26 } 27 while(carry)//还有进位 28 { 29 num[i][length++]=carry%10; 30 carry/=10; 31 } 32 carry=0; 33 for(j=length-1;j>=0;j--)//除法,从高位 34 { 35 temp=carry*10+num[i][j]; 36 num[i][j]=temp/(i+1); 37 carry=temp%(i+1); 38 }//肯定不会有借位到0的,都是整数 39 while(!num[i][length-1]) 40 { 41 length--; 42 } 43 b[i]=length; 44 } 45 } 46 int main() 47 { 48 int n,i; 49 catalan(); 50 while(scanf("%d",&n)!=EOF) 51 { 52 for(i=b[n]-1;i>=0;i--) 53 { 54 printf("%d",num[n][i]); 55 } 56 printf("\n"); 57 } 58 return 0; 59 }
这是比较简单的base是10的下附另外一种代码
1 //输出卡特兰数 2 //首先需要肯定,程序是正确的 3 //这算是大数乘除法!记住他们是如何处理的!由于数据很大,用基本数据类型根本无法满足要求,只能用数组来表示! 4 #include <iostream> 5 #include<cstdio> 6 #include<memory.h> 7 using namespace std; 8 #define MAX 101 9 #define BASE 10000//base只是一个基度,对最终取值并没有影响,相反,base取值愈大,计算量愈小 10 //base发生改变的时候,下面的输出也要相应地做出调整,否则也会输出错误答案!除非当base取10! 11 void multiply(int a[],int len,int b)//乘法 12 { 13 for(int i=len-1,carry=0;i>=0;--i)//从最后一位开始相乘,依次向前与每一位相乘 14 {//问题在于,为什么BASE=10000? 15 carry+=b*a[i]; 16 a[i]=carry%BASE; 17 carry/=BASE; 18 //cout<<"carry="<<carry<<" "<<"a["<<i<<"]="<<a[i]<<endl;//以4个0为一组 19 } 20 } 21 void divide(int a[],int len,int b)//除法,很妙的!这种除法可能想不到,仔细体会! 22 {//应当如何除呢? 23 for(int i=0,div=0;i<len;++i)//从高位除起 24 { 25 div=div*BASE+a[i]; 26 a[i]=div/b;//b为除数 27 div%=b; 28 } 29 } 30 int main() 31 { 32 int i,j,h[101][MAX]; 33 memset(h[1],0,MAX*sizeof(int));//赋值,每一个都置为0 34 for(i=2,h[1][MAX-1]=1;i<=100;++i)//运用递归,并且h[1]=1; 35 { 36 memcpy(h[i],h[i-1],MAX*sizeof(int));//h[i]=h[i-1];按字节拷贝,保证了h[i]和h[i-1]指向数组的一致性 37 multiply(h[i],MAX,4*i-2);//h[i]*=(4*i-2); 38 divide(h[i],MAX,i+1);//h[i]/=(i+1); 39 }//递归得到前100项的卡特兰数! 40 while(cin>>i && i>=1 && i<=100)//输入i的值 41 { 42 // for(i=1;i<=100;i++) 43 // { 44 for(j=0;j<MAX && h[i][j]==0;++j);//从0位开始搜索,找到不为0的第一个数 45 //printf("%d\n",EOF);在c语言中,EOF=-1; 46 printf("%d",h[i][j++]);//像是这个输出,就很妙了,第一位可能不足四位,就地输出! 47 for(;j<MAX;++j) 48 { 49 // if(h[i][j]==0) 50 printf("%04d",h[i][j]);//处在中间的值也可能没有四位,这时候要注意了,往左边加0,凑足4位,不然答案会出错! 51 // else 52 // printf("%d",h[i][j]);//不断输出值 53 54 } 55 56 printf("\n"); 57 } 58 system("pause"); 59 60 return 0; 61 }
原文:http://www.cnblogs.com/linminxuan/p/4469925.html