原题:
Another common social inability is known as ACM (Abnormally Compulsive Meditation). This psy-
chological 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 ≤ 300) 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
中文:
给你一个数n,表示有n个节点,每个节点都不一样。现在问你这n个节点组成一个二叉树都多少种方法?
#include<bits/stdc++.h>
using namespace std;
const int maxn=1000;
class bign
{
friend istream& operator>>(istream&,bign&);/*输入运算符友元*/
friend ostream& operator<<(ostream&,const bign&);/*输出运算符友元*/
friend bign operator+(const bign&,const bign&);/*加号运算符友元*/
friend bign operator*(const bign&,const bign&);/*乘号运算符友元*/
friend bign operator*(const bign&,int);/*高精度乘以低精度乘法友元*/
friend bign operator-(const bign&,const bign&);/*减号运算符友元*/
friend bign operator/(const bign&,const bign&);/*除法运算符友元*/
friend bign operator%(const bign&,const bign&);/*模运算符友元*/
friend bool operator<(const bign&,const bign&);/*逻辑小于符友元*/
friend bool operator>(const bign&,const bign&);/*逻辑大于符友元*/
friend bool operator<=(const bign&,const bign&);/*逻辑小于等于符友元*/
friend bool operator>=(const bign&,const bign&);/*逻辑大于等于符友元*/
friend bool operator==(const bign&,const bign&);/*逻辑等符友元*/
friend bool operator!=(const bign&,const bign&);/*逻辑不等符友元*/
private:
int len,s[maxn];
public:
bign(){memset(s,0,sizeof(s));len=1;}
bign operator=(const char* num)
{
int i=0,ol;
ol=len=strlen(num);
while(num[i++]=='0'&&len>1)
len--;
memset(s,0,sizeof(s));
for(i=0;i<len;i++)
s[i]=num[ol-i-1]-'0';
return *this;
}
bign operator=(int num)
{
char s[maxn];
sprintf(s,"%d",num);
*this=s;
return *this;
}
bign(int num){*this=num;}
bign(const char* num){*this=num;}
string str() const
{
int i;
string res="";
for(i=0;i<len;i++)res=char(s[i]+'0')+res;
if(res=="")res="0";
return res;
}
};
bool operator<(const bign& a,const bign& b)
{
int i;
if(a.len!=b.len)return a.len<b.len;
for(i=a.len-1;i>=0;i--)
if(a.s[i]!=b.s[i])#include<bits/stdc++.h>
using namespace std;
const int maxn=1000;/*精度位数*/
/*(必选)类与基础功能定义,用法类似于unsigned(非负)*/
class bign
{
friend istream& operator>>(istream&,bign&);/*输入运算符友元*/
friend ostream& operator<<(ostream&,const bign&);/*输出运算符友元*/
friend bign operator+(const bign&,const bign&);/*加号运算符友元*/
friend bign operator*(const bign&,const bign&);/*乘号运算符友元*/
friend bign operator*(const bign&,int);/*高精度乘以低精度乘法友元*/
friend bign operator-(const bign&,const bign&);/*减号运算符友元*/
friend bign operator/(const bign&,const bign&);/*除法运算符友元*/
friend bign operator%(const bign&,const bign&);/*模运算符友元*/
friend bool operator<(const bign&,const bign&);/*逻辑小于符友元*/
friend bool operator>(const bign&,const bign&);/*逻辑大于符友元*/
friend bool operator<=(const bign&,const bign&);/*逻辑小于等于符友元*/
friend bool operator>=(const bign&,const bign&);/*逻辑大于等于符友元*/
friend bool operator==(const bign&,const bign&);/*逻辑等符友元*/
friend bool operator!=(const bign&,const bign&);/*逻辑不等符友元*/
private:
int len,s[maxn];
public:
bign(){memset(s,0,sizeof(s));len=1;}
bign operator=(const char* num)
{
int i=0,ol;
ol=len=strlen(num);
while(num[i++]=='0'&&len>1)
len--;
memset(s,0,sizeof(s));
for(i=0;i<len;i++)
s[i]=num[ol-i-1]-'0';
return *this;
}
bign operator=(int num)
{
char s[maxn];
sprintf(s,"%d",num);
*this=s;
return *this;
}
bign(int num){*this=num;}
bign(const char* num){*this=num;}
string str() const
{
int i;
string res="";
for(i=0;i<len;i++)res=char(s[i]+'0')+res;
if(res=="")res="0";
return res;
}
};
/*(可选)基本逻辑运算符重载*/
bool operator<(const bign& a,const bign& b)
{
int i;
if(a.len!=b.len)return a.len<b.len;
for(i=a.len-1;i>=0;i--)
if(a.s[i]!=b.s[i])
return a.s[i]<b.s[i];
return false;
}
bool operator>(const bign& a,const bign& b){return b<a;}
bool operator<=(const bign& a,const bign& b){return !(a>b);}
bool operator>=(const bign& a,const bign& b){return !(a<b);}
bool operator!=(const bign& a,const bign& b){return a<b||a>b;}
bool operator==(const bign& a,const bign& b){return !(a<b||a>b);}
/*(可选)加法运算符重载*/
bign operator+(const bign& a,const bign& b)
{
int i,max=(a.len>b.len?a.len:b.len),t,c;
bign sum;
sum.len=0;
for(i=0,c=0;c||i<max;i++)
{
t=c;
if(i<a.len)t+=a.s[i];
if(i<b.len)t+=b.s[i];
sum.s[sum.len++]=t%10;
c=t/10;
}
return sum;
}
/*(可选)乘法运算符重载(高精度乘高精度)*/
bign operator*(const bign& a,const bign& b)
{
int i,j;
bign res;
for(i=0;i<a.len;i++)
{
for(j=0;j<b.len;j++)
{
res.s[i+j]+=(a.s[i]*b.s[j]);
res.s[i+j+1]+=res.s[i+j]/10;
res.s[i+j]%=10;
}
}
res.len=a.len+b.len;
while(res.s[res.len-1]==0&&res.len>1)res.len--;
if(res.s[res.len])res.len++;
return res;
}
/*高精度乘以低精度(注意:必须是bign*int顺序不能颠倒,要么会与高精度乘高精度发生冲突*/
bign operator*(const bign& a,int b)
{
int i,t,c=0;
bign res;
for(i=0;i<a.len;i++)
{
t=a.s[i]*b+c;
res.s[i]=t%10;
c=t/10;
}
res.len=a.len;
while(c!=0)
{
res.s[i++]=c%10;
c/=10;
res.len++;
}
return res;
}
/*(可选)减法运算符重载*/
bign operator-(const bign& a,const bign& b)
{
bign res;
int i,len=(a.len>b.len)?a.len:b.len;
for(i=0;i<len;i++)
{
res.s[i]+=a.s[i]-b.s[i];
if(res.s[i]<0)
{
res.s[i]+=10;
res.s[i+1]--;
}
}
while(res.s[len-1]==0&&len>1)len--;
res.len=len;
return res;
}
/*(可选)除法运算符重载(注意:减法和乘法运算和>=运算符必选)*/
bign operator/(const bign& a,const bign& b)
{
int i,len=a.len;
bign res,f;
for(i=len-1;i>=0;i--)
{
f=f*10;
f.s[0]=a.s[i];
while(f>=b)
{
f=f-b;
res.s[i]++;
}
}
while(res.s[len-1]==0&&len>1)len--;
res.len=len;
return res;
}
/*(可选)模运算符重载(注意:减法和乘法运算和>=运算符必选)*/
bign operator%(const bign& a,const bign& b)
{
int i,len=a.len;
bign res,f;
for(i=len-1;i>=0;i--)
{
f=f*10;
f.s[0]=a.s[i];
while(f>=b)
{
f=f-b;
res.s[i]++;
}
}
return f;
}
/*(可选)X等运算符重载(注意:X法必选)*/
bign& operator+=(bign& a,const bign& b)
{
a=a+b;
return a;
}
bign& operator-=(bign& a,const bign& b)
{
a=a-b;
return a;
}
bign& operator*=(bign& a,const bign& b)
{
a=a*b;
return a;
}
bign& operator/=(bign& a,const bign& b)
{
a=a/b;
return a;
}
/*可选前缀++/--与后缀++/--(注意:加法必选)*/
bign& operator++(bign& a)
{
a=a+1;
return a;
}
bign& operator++(bign& a,int)
{
bign t=a;
a=a+1;
return t;
}
bign& operator--(bign& a)
{
a=a-1;
return a;
}
bign& operator--(bign& a,int)
{
bign t=a;
a=a-1;
return t;
}
istream& operator>>(istream &in,bign& x)
{
string s;
in>>s;
x=s.c_str();
return in;
}
ostream& operator<<(ostream &out,const bign& x)
{
out<<x.str();
return out;
}
bign b[301];
int main()
{
ios::sync_with_stdio(false);
b[1]=1;
for(int i=2;i<=300;i++)
{
bign tmp=1;
for(int j=2+i;j<=2*i;j++)
tmp=tmp*j;
b[i]=tmp;
}
int n;
while(cin>>n,n)
{
cout<<b[n]<<endl;
}
return 0;
}
解答:
看到题目,不考虑节点不同,一个二叉树有多少种方法?很经典的一个问题,答案是有卡特兰数个。现在每个节点都有编号,那么把所有的树的编号全排列即可。
所以
F(n)=
(2nn)/(n+1)×n!
化简以后就是答案~