题目链接:https://vjudge.net/problem/UVA-679
参考自:刘汝佳的紫书
思路:
我们发现,对于每一颗子树,假如小球是第奇数次到达这颗子树的根节点时,那么此时应该向左子树走,如果是偶数次,则向右子树方向走,假如现在给出了一组输入depth,num,即深度为depth的二叉树,求第num个小球落到的位置,那么我们发现,对于每一颗子树来说,假如现在是第num次到达这颗树的根节点,如果num为奇数,那么它应该向左子树方向走,并且是第(num+1)/2次到达左子树的根节点,如果num是偶数,那么它应该要向右走,并且是第num/2次到达右子树的根节点,这样我们一直向下,按照这个思路计算就可以得出结果。
代码:
#include<iostream> #include<cstring> #include<algorithm> #include<queue> #include<map> #include<stack> #include<cmath> #include<vector> #include<set> #include<cstdio> #include<string> #include<deque> using namespace std; typedef long long LL; #define eps 1e-8 #define INF 0x3f3f3f3f #define maxn 1005 /*struct point{ int u,w; }; bool operator <(const point &s1,const point &s2) { if(s1.w!=s2.w) return s1.w>s2.w; else return s1.u>s2.u; }*/ inline int read(){ int f=1,x=0;char ch; do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9'); do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9'); return f*x; } int n,m,k,t; int main() { while(scanf("%d",&n)&&n!=-1){ int depth,num; for(int i=0;i<n;i++){ scanf("%d%d",&depth,&num); int ans=1; depth--;//先把第一层减了 while(depth){ if(num%2){//奇数次到达目前子树的根节点 ans=ans*2;//根节点的左子树编号是根节点编号*2 num=(num+1)/2;//第(num+1)/2次到达左子树的根节点 }else{ ans=ans*2+1; num=num/2; } depth--; } printf("%d\n",ans); } } return 0; }