您的位置:首页 > 其它

catalan 数 标准二维表。 高精度计算。

2013-11-24 12:40 411 查看
描述

设n 是一个正整数。2xn的标准2维表是由正整数1,2,…,2n 组成的2xn 数组,该数组的每行从左到右递增,每列从上到下递增。2xn的标准2维表全体记为Tab(n)。例如,当n=3时Tab(3)如下:



给定正整数n,计算Tab(n)中2´n的标准2 维表的个数。

输入
输入的第一行有1个正整数n

输出
输出计算出的Tab(n)中2xn的标准2维表的个数
样例输入
3
样例输出
5

将数字从1..2n 排序,依次插入二维表,
因为每一列升序排序,那么插入第一行可以看作是入栈操作, 插入第二行可以看做出栈操作, 标准二维表的数量符合catalan数。

高精度求catalan数函数:

a[i][j] 保存i对应的卡特兰数的倒数第j 位。

但是此题隐藏的数据规模为10000 。 那么便无法建立a[][]这个二维数组, 只能牺牲效率,采用递推的方法计算输入的每一个n。
代码:
#include<iostream>

#include<algorithm>

using namespace std;

int a[10001] = {0};

int aa[10001]={0};

int main()

{

int n,i,j,len,r,temp,t;

int b[10001];

cin>>n;



// a[1][0] = 1; // ??????????????????????????????

aa[0]=1;

len = 1;

b[1] = 1;

for (i = 2; i <= n; i++)

{

t = i - 1;

for (j=0;j<len;j++) // ????????????,???????????????

{

// a[i][j] = a[i-1][j] * (4 * t + 2);

a[j]=aa[j]* (4 * t + 2);

}

for (r = j = 0; j < len; j++) // ??????????????????

{

// temp = a[i][j] + r;

temp = a[j] + r;

// a[i][j] = temp % 10;

a[j] = temp % 10;

r = temp / 10;

}

while (r) // ????????????

{

// a[i][len++] = r % 10;

a[len++] = r % 10;

r /= 10;

}

for (j = len-1, r = 0; j >= 0; j--) // ??????????????????????????????

{

// temp = r * 10 + a[i][j];

temp = r * 10 + a[j];

// a[i][j] = temp / (t+2);

a[j] = temp / (t+2);

r = temp % (t+2);

}

while (!a[len-1]) // ???????????????

{

len--;

}

b[i] = len; // ?????????????????????

for(j=0;j<len;j++)

aa[j]=a[j];

}

for(j = b
- 1; j >= 0; j--)

{

printf("%d",aa[j]);

}

printf("\n");







return 0;

}

明显效率很低。

对于catalan数 C(n,2n)/(n+1)
可以分解为质因子相乘的形式。 那么乘法和除法可以简化为质因子指数的加减。
#include "iostream"

#define CARRYS 10000

int prmStatic(int *prm,int num) // 产生小于num的所有质数。

{

int total=0,i=2,j;

int *judge = new int[num+1];

for(j=1;j<=num;j++)

judge[j]=j;

while(i<num+1)

{

while(!judge[i]) i++;

prm[total]=i;

total++;

for(j=i;j<num+1;j+=i)

judge[j]=0;

}

return total;

}

void breakNum(int left,int right,int *prm,int *stat) //质因数分解

{

int k,m,n,t;

k=m=right,n=left,t=0;

while(prm[t]<=k)

{

while(left!=right)

{

left/=prm[t];

right/=prm[t];

stat[t] += (right-left);

}

t++;

right=m;

left=n;

}

}

void carryPro(int *poly, int carry, int total, int &curpos)

{

poly[curpos] += carry;

int i = poly[curpos]/CARRYS;

if((curpos<total)||carry)

{

poly[curpos]%= CARRYS;

curpos++;

carryPro(poly, i, total, curpos);

}

}

void mulAll(int&m,int *prm, int *result, int prmsum, int *Last)

//累乘

{

Last[0] = 1,m=1;

for(int i=0; i<prmsum; i++)

{

for(int t=0; t<result[i]; t++)

{

for(int k=0; k<m; k++)

Last[k] *= prm[i];

for(int j=0; j<m; j++)

if(Last[j]>=CARRYS)

{

int k = j+1;

carryPro(Last, Last[j]/CARRYS, m, k);

Last[j] %= CARRYS;

if(m<k+1) m = k+1;

break;

}

}

for(int j=m-1; j>=0; j--)

{

if(Last[j]!=0) break;

m--;

}

}

}

void Print(int polysum, int *last)

//输出结果

{

printf("%d",last[polysum-1]);

for(int i=polysum-2; i>=0; i--)

{

int j;

for (j=CARRYS/10;j;j/=10)

printf("%d",last[i]/j%10);

}

}

int main(){

freopen("input.txt","r",stdin);

freopen("output.txt","w",stdout);

int m,presum=0;

scanf("%d",&m);

int *prm = new int[m];

int *last = new int[1500];

memset(prm, 0, 4*m);

presum=prmStatic(prm,m*2);

int *mole = new int[presum];

int *denom = new int[presum];

memset(denom, 0, 4*presum);

memset(mole, 0, 4*presum);

breakNum(1, m+1,prm, denom);

breakNum(m, 2*m,prm, mole);

for(int i=0; i<presum; i++)

mole[i] = mole[i]-denom[i];

memset(last,0,6000);

mulAll(m,prm, mole, presum, last);

Print(m ,last);

delete []mole;

delete []prm;

delete []last;

return 0;

}

nTab(n)=2n*(2n-1)*…(n+2)/n!
nTab(n)=2n*(2n-1)*…(n+2)/n!
nTab(n)=2n*(2n-1)*…(n+2)/n!

nTab(n)=2n*(2n-1)*…(n+2)/n!
nTab(n)=2n*(2n-1)*…(n+2)/n!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: