题目大意:
给你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;
}