题目大意:在结点1处放一个小球,它会往下落,每个内结点有一个开关,初始全部关闭,当每次有小球落到一个开关上时,状态都会改变。当小球到达一个结点时,若该结点上的开关关闭,则往左走,否则向右走,直到走到叶子结点。
输入叶子深度d,小球个数I,假设I不超过整颗树的叶子个数。d<20。
分析:对于结点k,其左子结点,右子节点的编号分别为2k,2k+1。
超时代码:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
using namespace std;
const int maxn=1<<20;
int s[maxn];
int d,I,k;
int main()
{
while(scanf("%d %d",&d,&I)==2)
{
memset(s,0,sizeof(s));
int dep=(1<<d)-1;
for(int i=0;i<I;i++)
{
k=1;
for(;;)
{
s[k]=!s[k];
if(s[k]!=0) k=2*k;
else k=2*k+1;
if(k>dep) break;
}
}
printf("%d\n",k/2);
}
return 0;
}
正确代码:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
using namespace std;
const int maxn=20;
int s[1<<maxn];
int d,I,k;
int main()
{
int n;
while(scanf("%d",&n)==1)
{
if(n==-1) break;
while(n--)
{
scanf("%d %d",&d,&I);
k=1;
//memset(s,0,sizeof(s));
while(--d)
{
if(I%2!=0) //奇数
{
k=k*2;
I=(I+1)/2;
}
else //I是偶数
{
k=2*k+1;
I=I/2;
}
}
cout<<k<<endl;
}
}
return 0;
}