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!
设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!
相关文章推荐
- 分治与递归——标准二维表问题
- 9、 大数,高精度计算---大数阶乘
- Java解决高精度计算问题
- 使用oracle来计算方差及标准差
- 标准体重计算查询
- 高精度计算N!
- 大数,高精度计算---大数减法
- 大数,高精度计算---百位大数
- java处理高精度的商业计算
- SAP 标准成本、计划成本、目标成本、实际成本计算公式
- [转]高精度乘法计算
- 计算 变异系数 标准差 标准偏差 相关系数 平滑指数 回归系数等C++ 模板类
- matlab 计算均值,方差,标准差
- 关于循环群中阶数与(生成元及子群)的计算关系(2009年pku最后一道题,无官方明确给出的标准答案)
- 洛谷P1729 计算e值【高精度】
- 高精度计算模板——棋盘覆盖问题
- 高精度计算模板——棋盘覆盖问题
- 高精度计算,求一个小数的N次方(ACM1001)
- 【高精度计算 02】 大整数乘法
- Android学习小应用案例---根据身高和性别计算标准体重