HDU 5573 Binary Tree 2015上海现场赛B题
2015-12-10 14:31
489 查看
题目大意:
有一个深度无限的完全二叉树,每个节点有一个标号:根节点标号为1,之后对于标号为x的节点,左孩子标号为2x,右孩子标号为2x+1(其实就是zkw线段树的标号规则)。现在从根节点开始向下走k步(根节点也算一步),每到一个节点可以选择加上或减去节点的标号,求最终结果为N的走法,其中N>=1且题目保证有解。
思路:
首先,我们用二进制数mask表示取数的方法,1表示+,0表示-,顺序从左向右,最右一位表示最后一次取数的方法;用pos表示最后到达节点的标号。这样就可以唯一确定一种走法,且很容易写出计算最终结果的函数f(mask,pos)。如k=3,mask=5,pos=7表示的路径为1 +,3 -,7 +,f(5,7)=5。
为方便表述再定义F(mask,x,pos,y)为mask右x位确定,pos左y位确定后,f的取值范围
经过观察很容易得到以下结论
最后一个节点取法一定为+,即mask&1=1
在k确定,后x步取法确定(即mask的右x位确定),前y步走法(即pos前y位确定)的情况下,f取值连续,且当所有未确定位全部置0时取得最小值
根据上述条件,只需依次确定mask和pos的值就可以得到答案
初状态mask最右位必然为1,pos最左位必然为1外其它位均未确定,根据题目限制N必包含在取值范围中,即F(1,1,1 << k,1)包含N
1.确定mask
从右向左依次确定mask,比如当前已确定前i位(mask其它位全部置0),则
F(mask,i,1<< k,1)最小值为f(mask,1<< k)
检查f(mask^(1<< i),1<< k))是否大于N,如果不大于N,则F(mask^(1<< i),i+1,1<< k,0)必包含N,否则F(mask,i+1,1<< k,0)必包含N
2.确定pos
此时mask已确定
从左向右依次确定pos,比如已确定前i位(pos其它位全部置0),则
F(mask,k,pos,i)最小值为f(mask,pos)
检查f(mask,pos^(1<<(k-1-i)))是否大于N,如果不大于N,则F(mask,k,pos^(1<<(k-1-i)),i+1)必包含N,否则F(mask,k,pos,i+1)必包含N
最后根据mask和pos打印路径即可
求解f(mask,pos)函数的复杂度为k,最终的复杂度O(k^2)
另外先pos再确定mask也是可行的
代码:
Problem : 5573 ( Binary Tree ) Judge Status : Accepted
RunId : 15788211 Language : G++ Author : qsqx
有一个深度无限的完全二叉树,每个节点有一个标号:根节点标号为1,之后对于标号为x的节点,左孩子标号为2x,右孩子标号为2x+1(其实就是zkw线段树的标号规则)。现在从根节点开始向下走k步(根节点也算一步),每到一个节点可以选择加上或减去节点的标号,求最终结果为N的走法,其中N>=1且题目保证有解。
思路:
首先,我们用二进制数mask表示取数的方法,1表示+,0表示-,顺序从左向右,最右一位表示最后一次取数的方法;用pos表示最后到达节点的标号。这样就可以唯一确定一种走法,且很容易写出计算最终结果的函数f(mask,pos)。如k=3,mask=5,pos=7表示的路径为1 +,3 -,7 +,f(5,7)=5。
为方便表述再定义F(mask,x,pos,y)为mask右x位确定,pos左y位确定后,f的取值范围
经过观察很容易得到以下结论
最后一个节点取法一定为+,即mask&1=1
在k确定,后x步取法确定(即mask的右x位确定),前y步走法(即pos前y位确定)的情况下,f取值连续,且当所有未确定位全部置0时取得最小值
根据上述条件,只需依次确定mask和pos的值就可以得到答案
初状态mask最右位必然为1,pos最左位必然为1外其它位均未确定,根据题目限制N必包含在取值范围中,即F(1,1,1 << k,1)包含N
1.确定mask
从右向左依次确定mask,比如当前已确定前i位(mask其它位全部置0),则
F(mask,i,1<< k,1)最小值为f(mask,1<< k)
检查f(mask^(1<< i),1<< k))是否大于N,如果不大于N,则F(mask^(1<< i),i+1,1<< k,0)必包含N,否则F(mask,i+1,1<< k,0)必包含N
2.确定pos
此时mask已确定
从左向右依次确定pos,比如已确定前i位(pos其它位全部置0),则
F(mask,k,pos,i)最小值为f(mask,pos)
检查f(mask,pos^(1<<(k-1-i)))是否大于N,如果不大于N,则F(mask,k,pos^(1<<(k-1-i)),i+1)必包含N,否则F(mask,k,pos,i+1)必包含N
最后根据mask和pos打印路径即可
求解f(mask,pos)函数的复杂度为k,最终的复杂度O(k^2)
另外先pos再确定mask也是可行的
代码:
Problem : 5573 ( Binary Tree ) Judge Status : Accepted
RunId : 15788211 Language : G++ Author : qsqx
#include <iostream> #include <stdio.h> #include <queue> #include <map> 8dcc ; #include <algorithm> #include <string.h> #define ll long long #define forn(i,n) for(int i=0;i<(n);++i) #define rep(i,n) for(int i=1;i<=(n);++i) #define pii pair<int,int> #define mp(x,y) make_pair((x),(y)) using namespace std; ll f(ll mask,ll pos) { ll res = 0; while (pos) { if (mask & 1) res += pos; else res -= pos; pos >>= 1; mask >>= 1; } return res; } vector <pair<ll , char> >res; void print(ll mask,ll pos) { res.clear(); while (pos) { if (mask & 1) res.push_back(mp(pos, '+')); else res.push_back(mp(pos, '-')); pos >>= 1; mask >>= 1; } int len = res.size(); for (int i = len - 1; i >= 0; --i) { printf("%lld %c\n", res[i].first, res[i].second); } } void solve() { ll n; int k; cin >> n >> k; ll mask = 1; for (int t = 1; t <k;++t) { if (f(mask | (1LL << t), 1LL << (k - 1))<=n) { mask |= (1LL << t); } } ll pos = 1LL << (k - 1); for (int t = k - 2; t >= 0; --t) { if (f(mask, pos | (1LL << t)) <= n) pos |= (1LL << t); } print(mask, pos); } int main(){ //freopen("abc.txt", "r", stdin); int T; cin >> T; rep(t, T) { printf("Case #%d:\n",t); solve(); } return 0; }
相关文章推荐
- gulpfile.js 中的坑--注入篇(gulp-inject,gulp-wiredep)
- js取json数据笔记
- Linux学习笔记(二) - sort,uniq,cut,wc 命令详解
- leetcode:226 Invert Binary Tree-每日编程第七题
- Swift使用Playground编程
- MyEclipse SVN的使用
- CSS文件动态加载(续)
- Mac系统的JDK8默认安装路径
- Windowsコマンドの使い方(基本操作)
- LaunchMode加载模式
- leetcode:100 Same Tree-每日编程第六题
- (BUG) SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder"问题解决 .
- React-Native入门
- [原创][Verilog]个人.v文件书写规范
- java异常处理【转载】
- 黑马程序员————————IO流(图片加密)
- Spring mvc 接收json对象
- Eclipse最最最常用的快捷键
- leetcode:283 Move Zeroes-每日编程第五题
- getDimension()、getDimensionPixelOffset()和getDimensionPixelSize()区别详解