九度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 120 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; }
相关文章推荐
- 无法确定表达式的类型,因为<null>和int之间没有隐式转换
- TestNG timeOut example(java单元测试@Test timeOut)
- OAuth 2 开发人员指南(Spring security oauth2)
- 用scheme实现KMP算法
- 检查手机网络状态是关网还是GPRS 还是WIFI
- 判断数据库中数据表是否存在
- 重新学javaweb---文件上传监听--进度条
- self和下划线的用法区别
- [kuangbin带你飞]专题十二 基础DP1 I - 最少拦截系统
- ACM小组的队列 coj 1225
- 千回百折:百度Java研发offer斩获记和经验分享
- 【转】如何自己开发一款js或者jquery插件
- Notification集合(一)
- sscanf()的用法
- Testng enabled example
- (原创)OrnLite数据库缓存的介绍以及使用、一对多三级关联表及其CRUD怎删查改等操作demo
- 数据库基本----SQL语句大全
- 国密SM4对称算法实现说明(原SMS4无线局域网算法标准)
- 两个导体盘之间的电场
- sar 找出系统瓶颈的利器