Problem Description
Another common social inability is known as ACM (Abnormally Compulsive Meditation). This psychological disorder is somewhat common among programmers. It can be described as the temporary (although frequent) loss of the faculty of speech when the whole power of the brain is applied to something extremely interesting or challenging.
Juan is a very gifted programmer, and has a severe case of ACM (he even participated in an ACM world championship a few months ago). Lately, his loved ones are worried about him, because he has found a new exciting problem to exercise his intellectual powers, and he has been speechless for several weeks now. The problem is the determination of the number of different labeled binary trees that can be built using exactly n different elements.
For example, given one element A, just one binary tree can be formed (using A as the root of the tree). With two elements, A and B, four different binary trees can be created, as shown in the figure.
If you are able to provide a solution for this problem, Juan will be able to talk again, and his friends and family will be forever grateful.
Input
The input will consist of several input cases, one per line. Each input case will be specified by the number n ( 1 ≤ n ≤ 100 ) of different elements that must be used to form the trees. A number 0 will mark the end of input and is not to be processed.
Output
For each input case print the number of binary trees that can be built using the n elements, followed by a newline character.
Sample Input
1
2
10
25
0
Sample Output
1
4
60949324800
75414671852339208296275849248768000000
Source
UVA
分析:
如果结点之间不区分,那么答案就是Catalan(n)
但是现在我们给每个结点都编上了编号
实际上就相当于在Catalan的基础上又乘上了一个全排列
最后答案就是:Catalan(n)*n!
tip
又是一道需要高精度的题
n<=100,所以我们可以先求出1~100的答案
之后O(1)输出就好了
这就启发我们:
如果数据范围较小,但是输出较多并且有较多重复
我们就可以考虑预处理出范围内的答案
最后O(1)输出
n=100的时候
答案是
83668813731927024711268882117380243222191749722895663025350640914710184372250456
81065763252100408384370875099755604477792721304918348893371737459906581789624186
1031582305812277285886602772480000000000000000000000000
数组不要开小了
写高乘低的时候,一定是大数每一位都乘较小的数
高乘高的
板子不要打错了
//这里写代码片
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int a[102][1002],jcc[102][1002];
int la[102],lj[102];
void mul(int u)
{
int c[1002];
memset(c,0,sizeof(c));
int n=la[u]+lj[u];
int len=max(la[u],lj[u]);
for (int i=1;i<=len;i++)
{
int d=0;
for (int j=1;j<=len;j++)
{
c[i+j-1]+=a[u][i]*jcc[u][j]+d; //+=
d=c[i+j-1]/10;
c[i+j-1]%=10;
}
c[i+len]=d;
}
while (c[n]==0) n--;
la[u]=n;
for (int i=1;i<=n;i++) a[u][i]=c[i];
}
void catalan()
{
la[1]=1; a[1][1]=1;
int ll=1;
for (int i=2;i<=100;i++)
{
int d=0;
for (int j=1;j<=ll;j++) //高乘低
{
a[i][j]=a[i-1][j]*(4*i-2)+d;
d=a[i][j]/10;
a[i][j]%=10;
}
while (d)
{
a[i][++ll]=d;
d=a[i][ll]/10;
a[i][ll]%=10;
}
d=0;
for (int j=ll;j>=1;j--) //高除低
{
int t=d*10+a[i][j];
a[i][j]=t/(i+1);
d=t%(i+1);
}
while (a[i][ll]==0) ll--;
la[i]=ll;
}
}
void jc()
{
lj[1]=1; jcc[1][1]=1;
int ll=1;
for (int i=2;i<=100;i++)
{
int d=0;
for (int j=1;j<=ll;j++)
{
jcc[i][j]=jcc[i-1][j]*i+d;
d=jcc[i][j]/10;
jcc[i][j]%=10;
}
while (d)
{
jcc[i][++ll]=d;
d=jcc[i][ll]/10;
jcc[i][ll]%=10;
}
lj[i]=ll;
}
}
int main()
{
catalan();
jc();
for (int i=1;i<=100;i++)
mul(i);
int n;
scanf("%d",&n);
while (n)
{
for (int i=la[n];i>=1;i--)
printf("%d",a[n][i]);
printf("\n");
scanf("%d",&n);
}
return 0;
}