uva 10303 How Many Trees?

组合数学,递推(Catalan number , 卡特兰数)

题目:给n个数字,能构建成多少种二叉排序树。这个问题并不难,用递归的思想就能解决。当空树即n=0时方案数为1,当n=1时方案数同样为1。当n>=2时,我们把n个数按升序排列,如果我们选ai作为数树根,那么a1……ai-1必定在有子树,ai+1……an必定在左子树,左子树有i-1个元素,同样是排序二叉树,相当于问这个i-1个元素又能组成多少个二叉排序树,右子树有n-i个元素,同时是二叉排序树,相当于问这n-i个元素能组成多少个二叉排序树,方案数为两者相乘。

对于每个ai作为树根的计算方法如上,而所有的ai都能作为树根,所以不能总结出公式

h(n)= h(0)*h(n-1)+h(1)*h(n-2) + ... + h(n-1)h(0) (n>=2)

由于n去到1000,是个很大的数,要用到高进度

但是发现用上面的公式去推必须为二重循环,会超时,所以没办法去找报告,才知道这个数列其实是卡特兰数,然后查了卡特兰数的相关资料,得到了不同的递推公式,下面这个递推公式就是正解

h(n)=h(n-1)*(4*n-2)/(n+1);

 

 

用这个公式,高精度乘法为int乘高精度,高精度除法为int除高精度,还是比较好写的

#include <cstdio>

#include <cstring>



#define N 2000



int maxlen;

struct num

{

    int a[N+50],len;

}big[N];



void add(struct num &p ,struct num t)

{

    int max=p.len>t.len?p.len:t.len;

    int i,c=0;

    for(i=0; i<max; i++)

    { p.a[i]+=(t.a[i]+c); c=p.a[i]/10; p.a[i]%=10;}

    if(c) p.a[i++]=c;

    p.len=i;

}



void mul(struct num &p , struct num q , int x)

{

   int s;

   for(int i=0; i<q.len; i++)

   {

       s=q.a[i]*x;

       struct num t;

       int j=i;

       memset(t.a,0,sizeof(t.a)); t.len=0;

       while(s)

       { t.a[j]=s%10; s/=10; j++; }

       t.len=j;

       add(p,t);

   }

}



void div(struct num &p , int y)

{

    int i=p.len-1, x=0 , k=0 , j;

    int ans[N+50];

    memset(ans,0,sizeof(ans));

    while(i>=0)

    {

        while(x<y && i>=0)

        { x=(x*10+p.a[i]); i--; ans[k++]=0; }

        k--;

        ans[k++]=x/y;

        x%=y;

    }



    for(i=0; ;i++) if(ans[i]) break;  //消除前导0

    for(p.len=k-i , j=p.len-1; i<k ; j--,i++) p.a[j]=ans[i];

}

int main()

{

    memset(big,0,sizeof(big));

    big[0].a[0]=1; big[0].len=1;

    big[1].a[0]=1; big[1].len=1;



    for(int n=2; n<=1000; n++)

    {

        //h(n)=h(n-1)*(4*n-2)/(n+1)

        mul(big[n] , big[n-1] , 4*n-2);

        div(big[n] , n+1);

    }



    int n;

    while(scanf("%d",&n)!=EOF)

    {

        for(int i=big[n].len-1; i>=0; i--)

            printf("%d",big[n].a[i]);

        printf("\n");

    }

    return 0;

}

 

你可能感兴趣的:(tree)