题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=620
题 意:有一颗满二叉树,每个节点是一个开关,初始全是关闭的,小球从顶点落下,
小球每次经过开关就会把它的状态置反,现在问第k个球下落到d层时经过的开关编号。
思 路:按题意直接模拟即可,但不能模拟全过程。而是找到规律:当最后一个小球I是奇数,则他是往左走的第(I+1)/2个小球;当他是偶数时,他是往右走的第I/2个小球,所以可以直接模拟最后一个小球。
代码如下:
超时代码:
#include <iostream>
using namespace std;
#include <string.h>
#include <stdio.h>
#include <stack>
#include <algorithm>
int vis[1<<20];
int main()
{
int T;
while( scanf( "%d", &T ) != EOF )
{
if( T == -1 ) break;
while( T-- )
{
int d,I,k;
scanf ( "%d %d", &d, &I );
int n = (1<<d) - 1;
memset(vis,0,sizeof(vis));
for( int i = 0; i < I; i ++ )
{
k = 1;
while(1)
{
vis[k] = !vis[k];
k = vis[k] ? k*2:k*2+1;
if(k>n) break;
}
}
printf("%d\n",k/2);
}
}
return 0;
}
AC代码:
#include <iostream>
using namespace std;
#include <string.h>
#include <stdio.h>
#include <stack>
#include <algorithm>
int main()
{
int T;
while( scanf( "%d", &T ) != EOF )
{
if( T == -1 ) break;
while( T-- )
{
int d,I,k;
scanf ( "%d %d", &d, &I );
k = 1;
for( int i = 0; i < d-1; i ++ )
{
if(I%2) {k=k*2;I=(I+1)/2;}
else { k = k*2+1;I/=2;}
}
printf("%d\n",k);
}
}
return 0;
}