POJ 2775 (卢卡斯+二叉树)

本文探讨了使用数组和指针实现二叉树的方法,并对比了两种方式的时间和空间效率。通过具体的代码示例,展示了如何进行节点插入、递归遍历及计算组合数等操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一种数组做法,一种指针做法
这里写图片描述
可以看出指针比数组所用时间少而且所占内存也少
不懂卢卡斯点这里传送门

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include<cstring>

using namespace std;

struct node{
    int idx;
    int size;
}a[1000000];

int ans;

void myinsert(int x){
    int p=1;
    while(a[p].size){
        a[p].size++;
        if(x>a[p].idx) p=2*p+1;
        else p=2*p;
//        cout<<"123"<<endl;
    }
    a[p].idx=x;
    a[p].size=1;
}

typedef long long ll;
int quick_power_mod(int a,int b,int m){//pow(a,b)%m
    int result = 1;
    int base = a;
    while(b>0){
         if(b & 1==1){
            result = (result*base) % m;
         }
         base = (base*base) %m;
         b>>=1;
    }
    return result;
}
//计算组合数取模
ll comp(ll a, ll b, int p) {//composite num C(a,b)%p
    if(a < b)   return 0;
    if(a == b)  return 1;
    if(b > a - b)   b = a - b;

    int ans = 1, ca = 1, cb = 1;
    for(ll i = 0; i < b; ++i) {
        ca = (ca * (a - i))%p;
        cb = (cb * (b - i))%p;
    }
    ans = (ca*quick_power_mod(cb, p - 2, p)) % p;
    return ans;
}
ll lucas(ll n, ll m, ll p) {
     ll ans = 1;

     while(n&&m&&ans) {
        ans = (ans*comp(n%p, m%p, p)) % p;//also can be recusive
        n /= p;
        m /= p;
     }
     return ans;
}

int dfs(int t){
    if(a[t].size==0)
        return 1;
    else  return ((dfs(2*t+1)%9901*dfs(2*t))%9901*lucas(a[t].size-1,a[2*t].size,9901))%9901;
}

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF&&n){
        memset(a,0,sizeof(a));
        for(int i=0;i<n;i++){
            int x;
            scanf("%d",&x);
            if(i==0){
                a[1].idx=x;
                a[1].size=1;
            }else myinsert(x);
        }
//        printf("%d\n",a[1].size);
        ans=dfs(1);
        printf("%d\n",ans);
    }

    return 0;
}
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include<cstring>

using namespace std;

struct node{
    node* l;
    node* r;
    int idx;
    int size;
    node(){
        idx=0;
        size=0;
        l=NULL;
        r=NULL;
    }
};

node* root;

void myinsert(int x){
    node* t=root;
    while(t->size){
        t->size++;
        if(x<=t->idx){
//             printf("%d\n",t->idx);
            if(t->l!=NULL) t=t->l;
            else{
                t->l=new node;
                t=t->l;
            }

        }else{
//            printf("%d\n",t->idx);
            if(t->r!=NULL) t=t->r;
            else{
                t->r=new node;
                t=t->r;
            }
        }
    }
    t->idx=x;
    t->size=1;
}

typedef long long ll;
int quick_power_mod(int a,int b,int m){//pow(a,b)%m
    int result = 1;
    int base = a;
    while(b>0){
         if(b & 1==1){
            result = (result*base) % m;
         }
         base = (base*base) %m;
         b>>=1;
    }
    return result;
}
//计算组合数取模
ll comp(ll a, ll b, int p) {//composite num C(a,b)%p
    if(a < b)   return 0;
    if(a == b)  return 1;
    if(b > a - b)   b = a - b;

    int ans = 1, ca = 1, cb = 1;
    for(ll i = 0; i < b; ++i) {
        ca = (ca * (a - i))%p;
        cb = (cb * (b - i))%p;
    }
    ans = (ca*quick_power_mod(cb, p - 2, p)) % p;
    return ans;
}
ll lucas(ll n, ll m, ll p) {
     ll ans = 1;

     while(n&&m&&ans) {
        ans = (ans*comp(n%p, m%p, p)) % p;//also can be recusive
        n /= p;
        m /= p;
     }
     return ans;
}

int dfs(node* t){
//  if(t!=NULL)
//      printf("%d\n",t->idx);
    if(t==NULL||t->size==0)
        return 1;
    return (dfs(t->l)*dfs(t->r)*lucas(t->size-1,t->l==NULL?0:t->l->size,9901))%9901;

}

void del(node* &t){
    if(t==NULL) return;
    del(t->l);
    del(t->r);
    delete t;
}

void print(node* t){
    if(t==NULL) return ;
    print(t->l);
    print(t->r);
    printf("%d  ",t->idx);
}

int main()
{
    int n;
//        printf("%d\n",root->idx);
    while(scanf("%d",&n)!=EOF&&n){
        root=new node;
        for(int i=0;i<n;i++){
            int x;
            scanf("%d",&x);
            if(i==0){
                root->idx=x;
                root->size=1;
//                root->l=NULL;
//                root->r=NULL;
            }else myinsert(x);
        }
//        printf("%d\n",root->l->l==NULL?1:0);
//        print(root);
        int ans=dfs(root);
        printf("%d\n",ans);
        del(root);
    }

    return 0;
}
/*
9
5 6 3 18 20 10 4 17 20
*/
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值