题意:就是给一个深度为D的完全二叉树;然后给I个小球,初始时所有节点为0;如果来了一个小球,那么这个节点先变成1,然后这个球往左孩子走,如果再来一个球,那么这个节点就先变为0,然后往右孩子走;问最后一个小球落到的节点编号;
其实这道题我拿着感觉有点懵逼;最简单的想法就是每个节点每个球去枚举一下但是想想时间复杂度ITD,早就超时了;
但是我可以发现这个规律:
对1号节点,如果I为奇数,说明最后一个球会使得1号节点从0–》1,那么就是往左边走;(因为节点初始都为0);如果I是偶数,那么最后一个球就会使得1号节点从1–》0那么就会往右边走,所以我可以算出来2号节点有多少个球走,3号节点有多少个球走(因为这里是动态的,所以你想成这样就更好理解些:就是2号节点存了多少个球,3号节点存了多少个球);然后按照这个思路又从2,3开始这样分析,就可以知道每个节点所存的球的个数;最后根据层数来判定截止;所以AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int T,D,I;
int k;
void solve(){
while(T--){
scanf("%d %d",&D,&I);
k=1;//因为小球都是从第1个节点开始的
int d=1;//深度
while(d<D){//其实这里感觉就像第I个小球混着其他小球一个下降
if(I&1)k=2*k,I=(I+1)/2;//如果为有奇数的小球,那么他会往左走;并且左边会存有(I+1)/2个小球
else k=2*k+1,I=I/2;//如果有偶数个小球,那么他会往右走;并且右边会有I/2个小球;
d++;//然后下一层
}
printf("%d\n",k);
}
}
int main(){
scanf("%d",&T);//组数
if(T!=-1)solve();
return 0;
}