UVa 679. Dropping Balls

这个题是啥考点长的又不像大暴力

提交地址 VJudge

题目大意

有一棵深度为\(D\)的完美二叉树(假设根的深度为\(1\))。显然这棵树有\(2^{D-1}\)个叶结点。现在有\(2^{D-1}\)个小球依次从根结点向下滚。开始,所有结点的flag=false
将一个小球放在根结点,小球开始下落。当小球未落入任一叶结点时,若小球所在的结点的flag=false则往左儿子下落;flag=true则往右儿子下落。当小球落到任一叶结点时,下落结束,小球经过的所有结点的flag都要取反。如果还有球,就以同样规则放球(放了前面那些球后flag不会重置)。
求第\(I\)个下落的小球落在哪个叶结点。

分析

手玩一遍发现,对于题目描述中四层的完美二叉树,\(2^{4-1}=8\)个小球会依次落到\(8,\)\(12,\)\(10,\)\(14,\)\(9,\)\(13,\)\(11,\)\(15\)号结点,分别是第\(0,\)\(4,\)\(2,\)\(6,\)\(1,\)\(5,\)\(3,\)\(7\)个叶子结点,写成二进制再翻转一下……

叶结点顺序 0 4 2 6 1 5 3 7
二进制 000 100 010 110 001 101 110 111
翻转 000 001 010 011 100 101 110 111
十进制 0 1 2 3 4 5 6 7
因此对于每组输入的$I$,其对应的叶结点编号即为:将$I-1$的二进制翻转后$+2^{D-1}$。 ##程序 ```cpp #include int main() { int T; scanf("%d", &T); while (T--) { int D, I; scanf("%d%d", &D, &I); I--; int rev = 0; for (int i = 1; i < D; i++) { rev = (rev << 1) + (I & 1); I >>= 1; } printf("%d\n", rev + (1 << (D - 1)) ); } return 0; } ```
posted @ 2017-11-18 21:12  Planet6174  阅读(310)  评论(0编辑  收藏  举报