正题
大意
将汉诺塔的规则改为只能移动到相邻的柱子,然后求有n个圆盘时在第m步时每个盘所在的位置。
解题思路
我们先将3个盘的移动情况推出来:(1,1,1)->(2,1,1)->(3,1,1)->(3,2,1)->(2,2,1)->(1,2,1)->(1,3,1)->(2,3,1)->(3,3,1)->(3,3,2)->(2,3,2)->(1,3,2)->(1,2,2)->(2,2,2)->(3,2,2)->(3,1,2)->(2,1,2)->(1,1,2)->(1,1,3)->(2,1,3)->(3,1,3)->(3,2,3)->(2,2,3)->(1,2,3)->(1,3,3)->(2,3,3)->(3,3,3)->(3,3,3)
我们会发现第一个盘有循环节(1,2,3,3,2,1),而第二个盘有每个长度为3的(1,2,3,3,2,1),而第3个盘有长度为9的(1,2,3)。那么我们其实可以发现每个盘都有循环节(1,2,3,3,2,1),然后第i个盘每3i−13i−1轮进行一次变化。
这个方法也有正确性:因为我们看第一个盘,他必须在第3个盘时第2个盘才可以移动到第2个盘,而当第一个盘回到第1个盘时,第2个盘才可以向第3个盘移动,而第ii个盘和第个盘的关系也是一样的。
代码
#include<cstdio>
#include<cstring>
using namespace std;
const char mj[6]={'1','2','3','3','2','1'};//循环节
int t,n,m;
int main()
{scanf("%d",&t);for (int ti=1;ti<=t;ti++){scanf("%d%d",&n,&m);for (int i=1;i<=n;i++){putchar(mj[m%6]);//输出putchar(' ');m/=3;//加长变化时间}puts("");}
}