1. 程式人生 > >HDU 1130 How Many Trees?(卡特蘭數+大數)

HDU 1130 How Many Trees?(卡特蘭數+大數)

How Many Trees?

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)

Problem Description A binary search tree is a binary tree with root k such that any node v reachable from its left has label (v) <label (k) and any node w reachable from its right has label (w) > label (k). It is a search structure which can find a node with label x in O(n log n) average time, where n is the size of the tree (number of vertices). 

Given a number n, can you tell how many different binary search trees may be constructed with a set of numbers of size n such that each element of the set will be associated to the label of exactly one node in a binary search tree? 

Input The input will contain a number 1 <= i <= 100 per line representing the number of elements of the set.

Output You have to print a line in the output for each entry with the answer to the previous question.

Sample Input 1 2 3
Sample Output 1 2 5 /************************************************************************/

題意:首先題目介紹了二叉搜尋樹的概念(即在一棵二叉樹中,以任意結點為根時,它的左孩子的值都小於根的值,它的右孩子的值總是大於根自身的值,這樣的二叉樹就是二叉搜尋樹),然後給你一個數字n,讓你將1~n這n個數字填到結點上,問能使它成為一棵二叉搜尋樹的填法有多少種

首先,題目已經給出了n=1,n=2,n=3的解,我們不妨再算算看n=4的解:

①以數字1為整棵樹的根,那麼有如下5種情況


②以數字2為整棵樹的根,則有如下2種情況


③以數字3為整棵樹的根,因為與②是對稱的,所以同樣有2種情況,而以數字4為根則與①是對稱的,所以有5種情況

共計14種情況

那麼答案形成的就是這樣一個數列

1,2,5,14……

相信知道卡特蘭數的人此時都會有種似曾相識的感覺,沒錯,這就是卡特蘭數數列,不知道卡特蘭數的,可以點連結學習學習

而我們真正需要的就是卡特蘭數中的一個遞推式


其餘就是模擬大數乘法與除法的過程,詳細見程式碼,不明白的歡迎提出

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<stdlib.h>
#include<cmath>
#include<string>
#include<algorithm>
#include<iostream>
#define exp 1e-10
using namespace std;
const int N = 101;
const int inf = 2147483647;
const int mod = 2009;
int s[N][2*N];
int main()
{
    int n,i,j,res;
    s[1][1]=1;s[1][0]=1;
    for(i=2;i<N;i++)
    {
        for(j=1;j<=s[i-1][0];j++)
        {
            s[i][j]+=s[i-1][j]*(4*i-2);
            s[i][j+1]+=s[i][j]/10;
            s[i][j]%=10;
        }
        while(s[i][j])
        {
            s[i][j+1]+=s[i][j]/10;
            s[i][j]%=10;
            j++;
        }
        for(s[i][0]=--j,res=0;j>0;j--)
        {
            res=res*10+s[i][j];
            s[i][j]=res/(i+1);
            res%=(i+1);
        }
        while(!s[i][s[i][0]])
            s[i][0]--;
    }
    while(~scanf("%d",&n))
    {
        for(i=s[n][0];i>0;i--)
            printf("%d",s[n][i]);
        puts("");
    }
    return 0;
}
菜鳥成長記