【POJ2775】The Number of the Same BST(二叉搜索树+计数+lucas定理)

传送门

  • 题目:
    【POJ2775】The Number of the Same BST(二叉搜索树+计数+lucas定理)_第1张图片
    给出一个数列,由该数列可以确定一颗二叉搜索树。求此二叉搜索树可以由多少个不同的数列确定。树上最多有100个结点。
  • 解题思路:
    100个结点可能出现极端情况(链式,100层),不能用数组存,考虑动态开点用指针存储 , 记得清空树,回收空间
    当前结点t,递推式: a n s [ t ] = a n s [ l t ] ∗ a n s [ r t ] ∗ C s i z e [ t ] − 1 s i z e [ l t ] ans[t]=ans[lt]*ans[rt]*C_{size[t]-1}^{size[lt]} ans[t]=ans[lt]ans[rt]Csize[t]1size[lt]其中 a n s [ t ] ans[t] ans[t]表示结点t对应的子树(二叉搜索树)能有 a n s [ t ] ans[t] ans[t]个不同的数列确定;
    s i z e [ t ] size[t] size[t]表示结点t对应的子树大小(包括t本身);
    在数列中结点t肯定是第一个,在产生左子树和右子树的数列已经确定的前提下,剩余的 s i z e [ t ] − 1 size[t]-1 size[t]1个位置中有 s i z e [ l t ] size[lt] size[lt]个放左子树中的元素,剩余的放右子树中的元素。
    这里数据比较小, C s i z e [ t ] − 1 s i z e [ l t ] C_{size[t]-1}^{size[lt]} Csize[t]1size[lt]可以不用Lucas求。(主要是为了复习下lucas定理的写法)
  • ac代码:
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;
const ll mod = 9901;
const int maxn = 110;
int n, a[maxn];
struct node{
    node *l, *r;
    int v, Size;
    node(){l=r=NULL, v=Size=0;}
}b[110];//

node *root;
void insert(int v)
{
    //printf("%d\n", v);
    node *t = root;
    while(t->Size>0)
    {
        t->Size++;
        if(v<=t->v)
        {
            if(t->l==NULL) t->l = new node();
            t = t->l;
            //printf("l%d\n", t->v);
        }
        else
        {
            if(t->r==NULL) t->r = new node();
            t = t->r;
            //printf("r%d\n", t->v);
        }
    }
    t->v = v; t->Size = 1;
}
void del(node *t)
{
    if(t->l!=NULL) del(t->l);
    if(t->r!=NULL) del(t->r);
    //printf("%d\n", t->v);
    delete(t);
}
ll mul(ll a, ll b) {return (a%mod)*(b%mod)%mod;}
ll qpow(ll a, ll b)
{
    ll res = 1; a%=mod;
    while(b)
    {
        if(b&1) res = mul(res, a);
        a = mul(a, a);
        b>>=1;
    }
    return res;
}
ll com(ll a, ll b)//Ca^b
{
    //printf("%lld %lld\n", a, b);
    if(a<b) return 0;
    if(b==0 || a==b) return 1;
    b = min(b, a-b);
    ll ca = 1, cb = 1;
    for(int i = 0; i < b; i++)
    {
        ca = mul(ca, a-i);
        cb = mul(cb, i+1);
    }
    return  mul(ca, qpow(cb, mod-2));
}
ll lucas(ll a, ll b)
{
    if(b==0) return 1;
    return com(a%mod, b%mod)*lucas(a/mod, b/mod)%mod;
}
ll dfs(node *t)
{
    if(t==NULL) return 1;
    //printf("%d %d %d %d \n", t->l==NULL?0:t->l->v, t->r==NULL?0:t->r->v, t->v, t->Size);
    return mul(mul(dfs(t->l), dfs(t->r)), lucas(t->Size-1, t->l==NULL?0:t->l->Size));
}
int main()
{
    //freopen("/Users/zhangkanqi/Desktop/11.txt","r",stdin);
    while(scanf("%d", &n) && n)
    {
        for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
        root = new node();
        root->v = a[1]; root->Size = 1;
        for(int i = 2; i <= n; i++) insert(a[i]);
        printf("%lld\n", dfs(root));
        del(root);
    }
    return 0;
}

你可能感兴趣的:(二叉树,卢卡斯定理,计数题)