HDU 5573 Binary Tree(构造题)

http://acm.hdu.edu.cn/showproblem.php?pid=5573

题意:
给出一个满二叉树,根节点权值为1,左儿子为2*val,右儿子为2*val+1。现在有只青蛙从根节点出发,一步步往下走,在每个节点它都要选择加上该点的权值还是减去该点的权值,如果正好经过k个节点时总的权值和为n,那么这只青蛙就成功了,需要输出方案。

思路:

这道题目要注意到n<=(1<<k)。

所以如果每次都走这棵二叉树的左节点的话,权值就是1,2,4,8,10,那么它就可以组成小于(1<<k)的所有偶数,如果组成所有奇数的话,只要最后一步走右节点即可。

现在设走左节点的权值和是sum,那么多余的部分就是sum-n,那么我们只需要把(sum-n)/2这部分变成负数就可以,那么这里就又存在一个问题了,就是sum-n有可能是奇数,如果是这种情况的话就让最后一步走右节点,这样的话sum-n就又变成偶数了。

那么怎么去凑(sum-n)/2呢,很简单,还是根据二进制,相应位的节点改为负即可。

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 const int maxn = 100+5;
 5 typedef long long ll;
 6 
 7 int n, k;
 8 int a[maxn];
 9 
10 int main()
11 {
12     //freopen("in.txt","r",stdin);
13     int T;
14     int kase = 0;
15     scanf("%d",&T);
16     while(T--)
17     {
18         bool flag = false;
19         scanf("%d%d",&n,&k);
20         ll sum = (1<<k)-1;
21         ll rest = sum - n;
22         if(rest&1) {flag = true; rest++;}
23         rest/=2;
24         for(int i=0;i<k;i++)
25         {
26             if(rest&((ll)1<<i))  a[i]=0;
27             else a[i]=1;
28         }
29         printf("Case #%d:
",++kase);
30         for(int i=0;i<k;i++)
31         {
32             if(i!=k-1) printf("%lld ",(ll)1<<i);
33             else if(flag)  printf("%lld ",(ll)(1<<i)+1);
34             else printf("%lld ",(ll)1<<i);
35             if(a[i])  puts("+");
36             else puts("-");
37         }
38     }
39     return 0;
40 }
原文地址:https://www.cnblogs.com/zyb993963526/p/7837244.html