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