题目大意: 给你n个节点,然后求出能够组成的二叉树的个数,注意每个节点都有标号。 解题思路: 卡特兰数,然后每个节点都有标号,所以最后要再对节点全排列,即n! 先预处理105以内的卡特兰数,之后再乘上n! 卡特兰数的递推公式:h(n)=h(n-1)*(4*n-2)/(n+1);   h(0) = 1; 代码:
//h(n)=h(n-1)*(4*n-2)/(n+1);   h(0) = 1;
#include
using namespace std;
const int MAX_LEN = 10005;
const int MAX_NUM = 105;

int catalan[MAX_NUM][MAX_LEN];

void multip(int *ans, int b, int &len)
{
    int carry = 0;
    for(int i = 0; i < len; i++)
    {
        int temp = ans[i] * b + carry;
        ans[i] = temp % 10;
        carry = temp / 10;
    }
    while(carry)
    {
        len++;
        ans[len-1] = carry % 10;
        carry /= 10;
    }
    return ;
}

void division(int *cata, int b, int &len)
{
    int r = 0;
    for(int i = len - 1; i >= 0; i--)
    {
        int temp = cata[i] + r * 10;
        cata[i] = temp / b;
        r = temp % b;
    }
    while(!cata[len-1])
        len--;
    return ;
}

int main(void)
{
    int len[MAX_NUM];
    memset(catalan, 0, sizeof(catalan));
    memset(len, 0, sizeof(len));
    catalan[0][0] = 1;
    len[0] = 1;

    for(int i = 1; i < MAX_NUM; i++)
    {
        memcpy(catalan[i], catalan[i-1], sizeof(catalan[i-1]));
        len[i] = len[i-1];

        multip(catalan[i], 4 * i - 2, len[i]);
        division(catalan[i], i + 1, len[i]);
    }


    int n;
    while(scanf("%d", &n), n)
    {
        for(int i = 1; i <= n; i++)
            multip(catalan[n], i, len[n]);

        for(int j = len[n] - 1; j >= 0; j--)
        {
            printf("%d", catalan[n][j]);
        }
        printf("\n");

    }
    return 0;
}
posted on 2012-02-15 00:44  cchun  阅读(875)  评论(0编辑  收藏  举报