BC 61 Subtrees
2015-11-02 08:53
218 查看
问题描述
输入描述
输出描述
输入样例
输出样例
一棵有N个节点的完全二叉树,问有多少种子树所包含的节点数量不同。
输入描述
输入有多组数据,不超过1000组. 每组数据输入一行包含一个整数N.(1≤N≤1018)(1\leq N\leq {10}^{18})
输出描述
对于每组数据输出一行,表示不同节点数的子树有多少种.
输入样例
5 6 7 8
输出样例
3 4 3 5 这道题考到的是递推,因为是完全二叉树,所以总有一边的子树是满子树,而满子树的节点数不同的个数就是层数,所以可以每次去掉根节点, 然后减去满的那边,并将满子树的所有个数可能加进集合,统计个数就行了。#include <stdio.h> #include <set> #define LL long long const int maxn = 65; //2^65才能超过10^18 LL sum[maxn]; int main ( ) { LL n; int ans; std :: set < LL > vis; sum[0] = 1; for ( int i = 1; i < maxn; i ++ ) sum[i] = sum[i-1]*2; //把2的次方保存到数组,用左移时间会超限 while ( ~ scanf ( "%I64d", &n ) ) { vis.clear ( ); vis.insert ( n ); ans = 1; n --; //每次都去掉根节点 while ( n > 0 ) { int i; LL t = n; for ( i = 1; ; i ++ ) { if ( t-sum[i] < 0 ) break ; t = t-sum[i]; //能搜到的最大层数 } int m; if ( t >= sum[i-1] ) //大于等于上一层的一半时,往右 m = i; else //否则去掉右边部分,往左 m = i-1; LL s = 0; for ( int j = 0; j < m; j ++ ) { s = s+sum[j]; //统计删除层的每种个数 if ( vis.count ( s ) ) continue ; ans ++; vis.insert ( s ); } n = n-s; //去掉一边子树 if ( n && ! vis.count ( n ) ) //n!=0需要考虑 { ans ++; vis.insert ( n ); } n --; //去掉根节点 } printf ( "%d\n", ans ); } return 0; }
相关文章推荐
- 举例详解Java编程中HashMap的初始化以及遍历的方法
- Objective-C中Runtime
- 初始化
- 自动点击键盘左右键
- php防止用户重复提交表单
- 46~55岁是“多事之秋”
- hibernate二级缓存 Ehcache配置详解
- Jquery 全选、反选
- 关于Cocos2dx-JS在iOS8以上系统调用OpenGL进入后台时崩溃的解决办法
- hibernate配置文件hibernate.cfg.xml的详细解释
- Java 多态
- C++语言基础内容
- kafka.common.ConsumerRebalanceFailedException异常解决
- RunTime
- 关于Intent用法的几点学习笔记
- 关于UIview UIlabel Unbutton 的一些常用的属性方法(用以优化界面)
- Ubuntu下将XPS文件转换成PDF文件
- 在linux文本中打开出现乱码问题
- dubbo连接池爆满
- 菜鸟之路-09