您的位置:首页 > 其它

九度OJ - 1113 - 二叉树

2016-05-10 00:31 225 查看

题目描述



如上所示,由正整数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 12

0 0

样例输出

4

来源

2007年北京大学计算机研究生机试真题

普通的遍历或者是递归来求解是会超时的,所以用二叉树的几个性质来解决这个问题

深度为k的二叉树至多有2k-1个节点

具有n个节点的完全二叉树的深度为log2n+1;

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;

ll n, m;
ll ans;
ll leftt, rightt, deep_n, deep_m, deep_diff;

int main()
{
while(scanf("%lld %lld", &m, &n)!=EOF){
if(m==0 && n==0)
break;

ans = 0;

leftt = rightt = m;

deep_n = (int)(log(n)/log(2)+1);
deep_m = (int)(log(m)/log(2)+1);

deep_diff = deep_n - deep_m;

ans = ans + (int)pow(2, deep_diff)-1;

for(ll i = 1; i <= deep_diff; i++){
leftt = leftt*2;
rightt = rightt*2+1;
}

if(rightt <= n)
ans = ans + rightt - leftt + 1;
else if(leftt <= n)
ans = ans + n - leftt + 1;

printf("%lld\n", ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: