题目:
HowMany Trees?
TimeLimit:1000MS Memory Limit:30000KB
TotalSubmit:376 Accepted:160
Description
Abinary search tree is a binary tree with root k such that any node v reachablefrom its left has label (v) <label (k) and any node w reachable from itsright has label (w) > label (k). It is a search structure which can find anode with label x in O(n log n) average time, where n is the size of the tree(number of vertices).
Givena number n, can you tell how many different binary search trees may beconstructed with a set of numbers of size n such that each element of the setwill be associated to the label of exactly one node in a binary search tree?
Input
Theinput will contain a number 1 <= i <= 100 per line representing thenumber of elements of the set.
Output
Youhave to print a line in the output for each entry with the answer to theprevious question.
SampleInput
1
2
3
SampleOutput
1
2
5
Source
Uva
题目分析:
根据题意,只要确定了父节点,左右子树的节点数便确定了。因此可以依次枚举父节点编号,把所有情况累加,注意到树的递归定义,本题也可采用递归(或递推)的思想计算树的构造方法数。其实本题得出数据为卡特兰数列,同时还应注意到本题需要使用大整数的乘法和加法;
方法二:直接套用公式,需要使用大整数除法和乘法。
注意事项:
1. 乘法算法的效率问题:因为本题多次做乘法,在不计时间代价的前提下得出答案后还应根据答案适当减少用于存储数据的空间,这样可以减小两次for循环的执行次数,从而提高效率。
代码:
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
using namespace std;
struct Num //大整数类
{
int num[200]={};
Num(){memset(num,0,sizeof(num));}
Num(const string &s) //将数据倒置存放
{
int k=0;
int len=s.size();
for(int i=len-1;i>=0;--i)
{
num[k++]=(s[i]-'0');
}
}
void print()
{
int i;
for(i=70;i>=0;--i) //去除前倒0
{
if(num[i])
break;
}
for(;i>=0;--i)
{
printf("%d",num[i]);
}
printf("\n");
}
};
Num operator+(const Num &a,const Num&b)
{
Num c;
int i;
for(i=0;i<70;++i)
{
c.num[i]=a.num[i]+b.num[i];
}
for(i=0;i<70;++i)
{
c.num[i+1]+=c.num[i]/10;
c.num[i]%=10;
}
return c;
}
Num operator*(const Num &a,const Num&b)
{
Num ans;
int i,j;
for(i=0;i<70;++i) //此处可先将循环次数设较大,根据得出答案后在根据答案长度
{ //缩小循环次数,否则容易超时。
for(j=0;j<70;++j)
{
ans.num[i+j]+=a.num[i]*b.num[j];
}
}
for(i=0;i<105;++i)
{
ans.num[i+1]+=ans.num[i]/10;
ans.num[i]%=10;
}
return ans;
}
int main()
{
/*Numf0={"1"},f1={"1"},f2={"2"},f3={"5"},f4={"14"}; //测试类正确性
Num f5=f4*f0+f3*f1+f2*f2+f1*f3+f0*f4;
f5.print();*/
Num f[102];
f[0]={"1"};
f[1]={"1"};
f[2]={"2"};
f[3]={"5"};
int i,j;
for(i=4;i<101;++i)
{
for(j=0;j<i;++j)
{
f[i]=f[i]+f[j]*f[i-1-j];
}
}
int n;
/*for(i=1;i<101;++i) //测试输出速度,是否会超时等
f[i].print();*/
while(~scanf("%d",&n))
{
f[n].print();
}
return 0;
}