1. 程式人生 > >uva 1264 Binary Search Tree 不一樣的演算法

uva 1264 Binary Search Tree 不一樣的演算法

題目思路:想,從根結點開始每個結點是如何確定下來的,先根節點,他從n個位置中選n個出來,他肯定放在第1個,他是C(n,n),接著想根節點的右子樹結點,他能放在那些位置,首先先將根節點的左右子樹的而所有節點加起來,然後用C選出右結點的個數,也就是C[根結點左子樹結點個數+根結點右子樹節點個數][根結點右子樹結點個數],根節點右子樹結點一定是放在C出來的第一個,然後便可以列舉每個是右子樹的結點

AC程式碼

#include <iostream>
#include<bits/stdc++.h>
using namespace std;

int tree[5000000];
int num[5000000];
long long C[36][36];
long long maxx;
vector<int>vec;
#define mod 9999991

void insert(int root,int val)
{
    maxx=max(maxx,(long long)root);
    if(tree[root]==0)
    {
        vec.push_back(root);
        tree[root]=val;
        num[root]=1;
        return;
    }
    num[root]++;
    if(val<tree[root])
        insert(root<<1,val);
    else
        insert(root<<1|1,val);
}

int main()
{
    for(int i=0;i<=30;++i)
    {
        for(int j=0;j<=i;++j)
        {
            if(j==0||j==i)
                C[i][j]=1;
            else
                C[i][j]=C[i-1][j-1]+C[i-1][j];
        }
    }
    int t;
    scanf("%d",&t);
    int n;
    while(t--)
    {
        for(int i=0;i<vec.size();++i)
        {
            tree[vec[i]]=0;
            num[vec[i]]=0;
        }
        vec.clear();
        maxx=0;
        scanf("%d",&n);
        for(int i=1;i<=n;++i)
        {
            int x;
            scanf("%d",&x);
            insert(1,x);
        }
        long long ans=1;
        for(int i=0;i<vec.size();i++)
        {
            if(vec[i]&1)
                ans=ans*C[num[vec[i]]+num[vec[i]-1]][num[vec[i]]]%mod;//判斷是否是右子樹結點,如果是,就C[兄弟子樹全部結點個數+自己子樹全部節點個數][自己子樹全部節點個數]
        }
        printf("%lld\n",ans);
    }
    return 0;
}