某一个完全二叉树的节点的个数

问题:


题目

如上所示,由正整数1,2,3……组成了一颗特殊二叉树。我们已知这个二叉树的最后一个结点是n。现在的问题是,结点m所在的子树中一共包括多少个结点。

比如,n = 12,m = 3那么上图中的结点13,14,15以及后面的结点都是不存在的,结点m所在子树中包括的结点有3,6,7,12,因此结点m的所在子树中共有4个结点。

输入:

输入数据包括多行,每行给出一组测试数据,包括两个整数m,n (1 <= m <= n <= 1000000000)。最后一组测试数据中包括两个0,表示输入的结束,这组数据不用处理

输出:

对于每一组测试数据,输出一行,该行包含一个整数,给出结点m所在子树中包括的结点的数目。

例如:

3 7

142 6574

2 754

0 0

输出:

3

63

498

分析:

输入开头的节点和最后的节点,m,n

每行的节点的个数是以2的倍数递增,1,2,4,8...

每行开头节点是上一层最左边的2倍,比如第二层的元素是以6开头的,就是3*2,第三层是以12开头的,就是6*2

每行结尾节点是开头元素+个数-1,比如第二次末尾是6+2-1=7,第三层就是12+4-1=15

知道上述规律,就可以算个数了,只需要知道行数,个数就是2的i次方-1

退出循环,有两个条件:

1,可能n在开头和结尾的元素之间

2,可能n在这行的结尾和下一行的开头之间

代码:

#include

using namespace std;

int f(int n){

    int sum=1;

    for(int i=0;i

        sum*=2;

    }

    return sum;

}

int main(){

    long long n,m;

    while(cin>>n>>m){

        if(n==0&&m==0){

            break;

        }

        long long p=n,i=1,q=n;

        int count=1;//行数

        bool b=false;

        while(1){

            if(m>=p&&m<=q){//q就是每行的结尾的个数

                break;

            }

            if(m>=q&&m<2*p){//142 6574处理这种类型的,6574不在开头和结尾的范围之内,所以就判断一下这个元素是否在这行的结尾和下一行的开头的元素之间

                b=true;

                break;

            }

            p=2*p;//每行的开头元素

            i=2*i;//每行的元素的个数

            q=p+i-1;//每行的结尾的元素

            count++;

        }

        if(b){

            cout<

        }else{

            //元素个数

            int sum=f(count-1)-1;

            cout<

        }

    }

    return 0;

}

结果:

你可能感兴趣的:(某一个完全二叉树的节点的个数)