题意:有一颗深度为d的二叉树,i个小球从根节点向下落。每个节点上有一个开关,小球落在该节点上时,若开关为开则向右走;反之向左走。小球每经过一次开关,开关的状态改变一次。求第i个小球最终会落到哪个节点上。
思路:
1、模拟。定义一个数组bool a,用来存储开关情况。小球当前位置为k时,像左走为2*k,像右走为2*k+1。(TLE)
2、因为小球的下落是有规律的,假如第j个小球向左,那么j+1个小球一定会向右走。所以只关心最后一个小球的奇偶性即可。
注意:思路2中,如果忘记删除思路1中的a数组的初始化,会超时。
TLE代码:
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<set>
#include<map>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<deque>
using namespace std;
int l,d,s;
bool a[(1<<20)]={0};
int main() {
scanf("%d",&l);
while(l--){
memset(a,0,sizeof(a));
scanf("%d%d",&d,&s);
int n=(1<<d)-1;
int where=1;
for(int i=1;i<=s;i++){
where=1;
do{
if(a[where]==false) where*=2;
else where=where*2+1;
a[where/2]^=1;
}while(where<=n);
}
printf("%d\n",where/2);
}
return 0;
}
AC代码:
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<set>
#include<map>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<deque>
using namespace std;
int l,d,s;
int main() {
scanf("%d",&l);
while(l--){
scanf("%d%d",&d,&s);
int where=1;
do{
if(s%2==0){
where=where*2+1;
s/=2;
}else{
where*=2;
s=(s+1)/2;
}
d--;
}while(d>=2);
printf("%d\n",where);
}
return 0;
}