hdoj 5573 Binary Tree 【思维】

来源:互联网 发布:淘宝教育网视频看不了 编辑:程序博客网 时间:2024/05/16 15:51



Binary Tree

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 59    Accepted Submission(s): 32
Special Judge


Problem Description
The Old Frog King lives on the root of an infinite tree. According to the law, each node should connect to exactly two nodes on the next level, forming a full binary tree.

Since the king is professional in math, he sets a number to each node. Specifically, the root of the tree, where the King lives, is 1. Say froot=1.

And for each node u, labels as fu, the left child is fu×2 and right child is fu×2+1. The king looks at his tree kingdom, and feels satisfied.

Time flies, and the frog king gets sick. According to the old dark magic, there is a way for the king to live for another N years, only if he could collect exactly Nsoul gems.

Initially the king has zero soul gems, and he is now at the root. He will walk down, choosing left or right child to continue. Each time at node x, the number at the node is fx (remember froot=1), he can choose to increase his number of soul gem by fx, or decrease it by fx.

He will walk from the root, visit exactly K nodes (including the root), and do the increasement or decreasement as told. If at last the number is N, then he will succeed.

Noting as the soul gem is some kind of magic, the number of soul gems the king has could be negative.

Given NK, help the King find a way to collect exactly N soul gems by visiting exactly K nodes.
 

Input
First line contains an integer T, which indicates the number of test cases.

Every test case contains two integers N and K, which indicates soul gems the frog king want to collect and number of nodes he can visit.

 1T100.

 1N109.

 N2K260.
 

Output
For every test case, you should output "Case #x:" first, where x indicates the case number and counts from 1.

Then K lines follows, each line is formated as 'a b', where a is node label of the node the frog visited, and b is either '+' or '-' which means he increases / decreases his number by a.

It's guaranteed that there are at least one solution and if there are more than one solutions, you can output any of them.

 

Sample Input
25 310 4
 

Sample Output
Case #1:1 +3 -7 +Case #2:1 +3 +6 -12 +
 


给定一棵满二叉树,根节点编号1,节点的编号即为节点的价值。

题意:给定一个整数N和一个整数k,现在从根节点出发沿着树边遍历k个节点,对于每个节点,可以选择减去价值,也可以选择加上价值,让你最后得到N价值,要求输出路径。初始价值为0。


首先任何一个数D,我们总可以找到一些2^a + 2^b + ... + 2^c = D。至于a,b...c通过二进制位就可以求出。

思路:对于满二叉树,考虑第i层最左边节点的价值 = 前i-1层最左边节点价值之和 + 1。由于题目限制N<=2^k,这就意味着我们可以找到一个F = 2^(k+1) - 1(前k层价值之和)>= N,之后只需要去掉多余的数(F - N) / 2就可以了。这里需要注意F-N的结果,因为我们必须保证它为偶数。

一、当N为偶数时,F-N为奇数,那么我们可以让第k个节点不走最左边的而走临近的。这样F = 2^(k+1),而且F-N结果为偶数。

二、当N为奇数,F-N为偶数,不用处理。

最后我们的任务就是——在k个节点找到若干个节点使它们价值之和 为 (F-N) / 2,并把这些节点标记下来。

最终答案就是沿着最左边走k个节点,碰到标记的点减去价值,否则加上。


AC代码:


#include <cstdio>#include <cstring>#include <cmath>#include <cstdlib>#include <algorithm>#include <queue>#include <stack>#include <map>#include <vector>#define INF 0x3f3f3f#define eps 1e-8#define MAXN (100000+10)#define MAXM (100000)#define Ri(a) scanf("%d", &a)#define Rl(a) scanf("%lld", &a)#define Rf(a) scanf("%lf", &a)#define Rs(a) scanf("%s", a)#define Pi(a) printf("%d\n", (a))#define Pf(a) printf("%.2lf\n", (a))#define Pl(a) printf("%lld\n", (a))#define Ps(a) printf("%s\n", (a))#define W(a) while(a--)#define CLR(a, b) memset(a, (b), sizeof(a))#define MOD 1000000007#define LL long long#define lson o<<1, l, mid#define rson o<<1|1, mid+1, r#define ll o<<1#define rr o<<1|1using namespace std;LL f[70], ans[70];bool mark[70];void getf(){    f[0] = 1;    for(int i = 1; i <= 61; i++)       f[i] = f[i-1] * 2;}int main(){    getf();    int t, kcase = 1; Ri(t);    W(t)    {        LL N; int k;        Rl(N); Ri(k);        for(int i = 0; i < k; i++)            ans[i] = f[i];        LL dis = f[k] - 1 - N;        if(N % 2 == 0)        {            ans[k-1]++;            dis++;        }        dis /= 2;        int bit = 0; CLR(mark, false);        while(dis)        {            if(dis & 1LL)                mark[bit] = true;            ++bit;            dis >>= 1;        }        printf("Case #%d:\n", kcase++);        for(int i = 0; i < k; i++)        {            printf("%lld ", ans[i]);            if(mark[i])                printf("-\n");            else                printf("+\n");        }    }    return 0;}


0 0
原创粉丝点击