[HDOJ5573]Binary Tree(找规律,贪心)
2016-04-25 10:41
531 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5573
这个题……规律暂时还找不到,先贡献两发TLE的代码吧,一个dfs一个状压枚举。
ENUM
这个题想了很多天,想明白了其实还蛮简单的。
题目给了一棵满二叉树,按照层次遍历从左到右挨个编号1 2 3....问蛤蛤从根节点向下走,走到一个点可以加上当前节点编号也可以删掉当前节点编号。问走k层能否恰好续够n。
题目中给了一个条件:N≤2^K≤2^60
因为读题坑掉了没看到这个条件,浪费了很多时间在例如n=10 k=3的情况上。这种情况在我的搜索中是完全有结果的,但是实际上这个情况不会在题目中出现,因为8<10。
这样就好办了,我们考虑任何一个十进制数都可以表示为二进制,这个二进制表示了某一位上是否要加上对应的2的幂次。
(以上皆为口胡+脑补,正常题解在下面)
N<=2^k意味着我们总能找到第k+1个节点,使得N小于k+1节点的数值。既然如此,我们贪心地选取最左边的一条链。这样,最左边那个点必然是整层最小的。对于本题目而言,总有2^(k+1)-1≥n。
由于最左侧的链均为2的幂次,我们以前的知识中一定有这样一条规律:2^(k)-1=∑i(1,k-1)2^i。表达不清楚,举个例子:32-1=1+2+4+8+16。
我们假设整条长度为k链都是加的,那它的总和就是2^(k+1)-1,我们现在知道要求的n,那我们不需要的那部分的值为2^(k+1)-1-n。
假设这个值为x,那x也总是能表达为一个二进制数,我们只需要在这个链子上找到可以表示x的二进制数的位置,把它们标记为'-'即可。
这个题……规律暂时还找不到,先贡献两发TLE的代码吧,一个dfs一个状压枚举。
#include <algorithm> #include <iostream> #include <iomanip> #include <cstring> #include <climits> #include <complex> #include <fstream> #include <cassert> #include <cstdio> #include <bitset> #include <vector> #include <deque> #include <queue> #include <stack> #include <ctime> #include <set> #include <map> #include <cmath> using namespace std; typedef long long ll; const int maxn = 66; ll n, k; ll f[maxn]; ll ans[maxn]; bool sub[maxn]; void init() { f[0] = 1; for(int i = 1; i < maxn; i++) { f[i] = f[i-1] * 2; } } int main() { // freopen("in", "r", stdin); int T, _ = 1; init(); scanf("%d", &T); while(T--) { scanf("%I64d %I64d", &n, &k); for(int i = 1; i <= k; i++) ans[i] = f[i-1]; if(n % 2 == 0) ans[k]++; ll nn = 1 << k; bool exflag = 0; for(ll i = 1; i < nn; i++) { if(exflag) break; ll cur = 0; memset(sub, 0, sizeof(sub)); for(ll j = 1; j <= k; j++) { if((1 << j) & i) { sub[j] = 1; cur -= ans[j]; } else cur += ans[j]; } if(cur == n) exflag = 1; } printf("Case #%d:\n", _++); for(ll i = 1; i <= k; i++) { printf("%I64d ", ans[i]); if(sub[i]) printf("-\n"); else printf("+\n"); } } return 0; }
ENUM
这个题想了很多天,想明白了其实还蛮简单的。
题目给了一棵满二叉树,按照层次遍历从左到右挨个编号1 2 3....问蛤蛤从根节点向下走,走到一个点可以加上当前节点编号也可以删掉当前节点编号。问走k层能否恰好续够n。
题目中给了一个条件:N≤2^K≤2^60
因为读题坑掉了没看到这个条件,浪费了很多时间在例如n=10 k=3的情况上。这种情况在我的搜索中是完全有结果的,但是实际上这个情况不会在题目中出现,因为8<10。
这样就好办了,我们考虑任何一个十进制数都可以表示为二进制,这个二进制表示了某一位上是否要加上对应的2的幂次。
(以上皆为口胡+脑补,正常题解在下面)
N<=2^k意味着我们总能找到第k+1个节点,使得N小于k+1节点的数值。既然如此,我们贪心地选取最左边的一条链。这样,最左边那个点必然是整层最小的。对于本题目而言,总有2^(k+1)-1≥n。
由于最左侧的链均为2的幂次,我们以前的知识中一定有这样一条规律:2^(k)-1=∑i(1,k-1)2^i。表达不清楚,举个例子:32-1=1+2+4+8+16。
我们假设整条长度为k链都是加的,那它的总和就是2^(k+1)-1,我们现在知道要求的n,那我们不需要的那部分的值为2^(k+1)-1-n。
假设这个值为x,那x也总是能表达为一个二进制数,我们只需要在这个链子上找到可以表示x的二进制数的位置,把它们标记为'-'即可。
#include <algorithm> #include <iostream> #include <iomanip> #include <cstring> #include <climits> #include <complex> #include <fstream> #include <cassert> #include <cstdio> #include <bitset> #include <vector> #include <deque> #include <queue> #include <stack> #include <ctime> #include <set> #include <map> #include <cmath> using namespace std; typedef long long ll; const int maxn = 66; ll n, k; ll f[maxn]; ll ans[maxn]; bool sub[maxn]; void init() { f[0] = 1; for(int i = 1; i < maxn; i++) { f[i] = f[i-1] * 2; } } int main() { // freopen("in", "r", stdin); int T, _ = 1; init(); scanf("%d", &T); while(T--) { scanf("%I64d %I64d", &n, &k); memset(sub, 0, sizeof(sub)); for(int i = 1; i <= k; i++) ans[i] = f[i-1]; ll remain = f[k] - n - 1; if(n % 2 == 0) { ans[k]++; remain++; } remain >>= 1; int cnt = 1; while(remain) { if(remain % 2 == 1) sub[cnt] = 1; remain >>= 1; cnt++; } printf("Case #%d:\n", _++); for(int i = 1; i <= k; i++) { printf("%I64d ", ans[i]); sub[i] ? printf("-\n") : printf("+\n"); } } return 0; }
相关文章推荐
- 第四章之BootStrap表单与图片
- device eth0 does not seem to be present, delaying initialization
- javascript设计模式--原型模式
- Servlet中的并发问题
- Oracle 12c 和 Hadoop:大数据的最佳存储和处理办法
- JAVA--组合模式(Composite)--设计模式十一
- django-mvvm(django的FormObject)
- import javax.servlet 出错(真的很管用)
- 北京林业大学“计蒜客”杯程序设计竞赛 网络赛--易彰彪的一张表
- Android请求网络--第三方库Android-async-http的使用(6)
- 记录一次很蠢的设计
- box plots
- 响铃:SCRM 对比移动CRM,输赢全靠硬功夫
- Apache Httpd负载均衡Tomcat并实现Session Sticky和Session Cluster
- Exception raised during rendering: java.lang.System.arraycopy([CI[CII)V
- 图片较多的网站,如淘宝京东、美丽说花瓣、QQ空间、百度图片等都采用哪些技术优化图片展示?
- 提升SQLite数据插入效率低、速度慢的方法
- 阿里分析型数据库ads学习记录
- JAVA基础--适配器模式
- 前端程序员:月薪 5K 到 5 万,我干了啥(转)