码迷,mamicode.com
首页 > 其他好文 > 详细

ACM/ICPC2015上海现场赛B题题解

时间:2015-11-25 18:42:28      阅读:267      评论:0      收藏:0      [点我收藏+]

标签:

给你一棵完全二叉树,初始能量为0,根节点编号为1(也就是说最左边那条路上节点的编号分别是2^0,2^1,2^2…2^(h-1))。从根节点开始往下走k-1步,走到每个节点选择加上或减去这个节点的编号,问走完这k个节点时能量恰好为n的方案。Special Judge.

在队友的提醒下(TAT我真是讨厌鹰语)看明白了数据范围,很明显是一个考二进制性质的题。于是一上手我先把样例改成了走最左路线的情况。样例出的蛮良心,一个奇数一个偶数,刚好对应两条路线:一直走左儿子或者走k-2个左儿子最后一个走右儿子。

路线分析完了,现在解决判断加减的问题。很容易发现-1变到+1差2,-2变到+2差4,于是这个问题还是深♂入的玩二进制,把所有情况可以归结到n=1+tmp*2(偶数再+1)。n=1的情况非常好搞,就是一路减下来最后一步加,非常基础的数学问题。然后我们就可以根据tmp的二进制表示推出答案辣!

 

什么?你推不出?跟我往下看↓【推得出的童鞋可以跳过】

上文已经提到tmp=(n-1)/2。为什么除2呢,因为一加一减造成的差值是翻倍的。当然这个情况下n为奇数,偶数的话请先自行减一。

现在把它写成k-1位的二进制表达。因为n是正数,所以最后一个节点必然是+,不用考虑。以3 5为例,tmp=1,所以写出来了0001.这就表明在2^0的时候需要把-翻转成+,其他不变。输出结果:1+ 2- 4- 8- 16+ 是不是很神奇~因为写成二进制表示的每一位就对应了2^i即题中说的节点编号,所以这样构造是正确的。

现在证它可以满足所有情况。因为n是不小于1且不大于2的k次幂的,所以最大值最小值均可以满足要求。k-1位二进制的全排列共有2^(k-1)种,对应奇偶两种不同的结尾选择后共2^k种结果,与n∈[1,2^k]形成一一对应的关系。

此题到此结束。

 

下面附上代码:

技术分享
 1 #include <stdio.h>
 2 typedef long long LL;
 3 LL bit2[66];
 4 int bit[66];
 5 void init()
 6 {
 7     bit2[0] = 1;
 8     for (int i=1; i<63; i++)
 9         bit2[i] = bit2[i-1] * 2;
10 }
11 int main()
12 {
13     int t,n,k,cas=1;
14     init();
15     scanf("%d",&t);
16     while (t--) {
17         bool flag = false;          //标记n是否为奇数
18         scanf("%d%d",&n,&k);        //大概这样,我记不清n和k的顺序了
19         if (n & 1) flag = true;
20         else n--;
21         int tmp = (n - 1) / 2;
22         for (int i=0; i<k-1; i++) { //对应k-1位二进制表达的翻转
23             bit[i] = tmp & 1;
24             tmp >>= 1;
25         }
26         for (int i=0; i<k-1; i++) {
27             printf("%lld ",bit2[i]);
28             puts(bit[i] ? "+" : "-");
29         }
30         if (flag) printf("%lld +\n",bit2[k-1]);
31         else printf("%lld -\n",bit2[k-1]+1);
32     }
33     return 0;
34 }
View Code

 

//话说我看到有人说二分,并不太懂…这不是个纯纯的构造么…在此求教…

ACM/ICPC2015上海现场赛B题题解

标签:

原文地址:http://www.cnblogs.com/honeycat/p/4995177.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!