Problem Description
1,2,...,n表示n个盘子.数字大盘子就大.n个盘子放在第1根柱子上.大盘不能放在小盘上.在第1根柱子上的盘子是a[1],a[2],...,a[n]. a[1]=n,a[2]=n-1,...,a[n]=1.即a[1]是最下面的盘子.把n个盘子移动到第3根柱子.每次只能移动1个盘子,且大盘不能放在小盘上.问第m次移动的是哪一个盘子,从哪根柱子移到哪根柱子.例如:n=3,m=2. 回答是 :2 1 2,即移动的是2号盘,从第1根柱子移动到第2根柱子 。
Input
第1行是整数T,表示有T组数据,下面有T行,每行2个整数n (1 ≤ n ≤ 63) ,m≤ 2^n-1
Output
输出第m次移动的盘子号数和柱子的号数.
Sample Input
4 3 2 4 5 39 183251937942 63 3074457345618258570
Sample Output
2 1 2 1 3 1 2 2 3 2 2 3
先把情况列出来自己寻找规律吧
规律就是
如果总盘数与现在移动的盘子的号码同奇偶性,那么移动顺序是1->3->2->1
否则是1->2->3->1
记住这个移动顺序是对于同一个盘而言的
#include <stdio.h>
__int64 pow(__int64 n)
{
__int64 s = 1;
int i;
for(i = 1;i<=n;i++)
s*=2;
return s;
}
int main()
{
__int64 n,m,t;
int a[3][2] = {{3,1},{1,2},{2,3}},b[3][2] = {{2,1},{1,3},{3,2}};
int i,test;
scanf("%d",&test);
while(test--)
{
__int64 cnt = 0;
scanf("%I64d%I64d",&n,&m);
__int64 tem = m;
for(i = 1; i<=n; i++)
{
t = m%2;
if(t)
{
printf("%d ",i);
break;
}
else
m/=2;
}
if(tem%2)
cnt = (tem+1)/2;
else
{
m = tem;
__int64 sum = pow(i-1);
m = m-sum;
cnt = m/pow(i)+1;
}
int flag = 0;
if((n%2 && i%2) || (n%2 == 0 && i%2 == 0))
{
flag = 1;
}
cnt = cnt%3;
if(flag)
{
printf("%d %d\n",b[cnt][0],b[cnt][1]);
}
else
{
printf("%d %d\n",a[cnt][0],a[cnt][1]);
}
}
return 0;
}