题目描述
在印度,有这么一个古老的传说:在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石针。印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片,这就是所谓的汉诺塔。不论白天黑夜,总有一个僧侣在按照下面的法则移动这些金片:一次只移动一片,不管在哪根针上,小片必须在大片上面。僧侣们预言,当所有的金片都从梵天穿好的那根针上移到另外一根针上时,世界就将在一声霹雳中消灭,而梵塔、庙宇和众生也都将同归于尽。
现在请你计算出起始有m个金片的汉诺塔金片全部移动到另外一个针上时需要移动的最少步数是多少?(由于结果太大,现在只要求你算出结果的十进制位最后六位)
输入格式
第一行是一个整数N表示测试数据的组数(0<N<20)
每组测试数据的第一行是一个整数m,表示起始时金片的个数。(0<m<1000000000)输出格式
输出把金片起始针上全部移动到另外一个针上需要移动的最少步数的十进制表示的最后六位。
样例
样例输入
2 1 1000
Copy
样例输出
1 69375
/*由于怎么都不能完全理解传说中的快速幂,于是我想出了一种办法,来很好思考的解决这么一道题目*/
首先我们很容易可以判断出来这个所谓移动金片的步数其实就是2的n次幂-1(n是起始针上的金片数量)
然而这个n次幂如果硬算必然就会超时,那么该怎么让这个n次幂算起来能更简便呢?
这里就要注意题目中很重要的一点,“输出格式”----它居然只要求输出后六位就可以了!
对于2的n次方末位变化有一个规律是大家百度就可以搜到的,它的最后一位会是一个2,4,8,6(共4个)的循环......
而它的后两位变化就要除去开头的一个2,就变成了04,08,16,32,64,28,56,12,24,48,96,92,84,68,36,72,44,88,76,52(共20个)的循环......
此时聪明的你肯定发现了,对于2的n次幂,它的固定的量的末位数变化是一个有规律的循环,所以对于题目要求的2的n次幂的后六位,必然也是一个有规律的变化循环,但是和一位两位不同肯定不能单纯的枚举出来,这里我们就要用到计算机来寻找这个循环。
由于后一位是从2开始,后两位是从04开始,所以我们可以推出后三位是从008开始,后四位是从0016,后五位是00032,因此后六位的循环便是从000064开始的。
这里用到我们可亲可敬的卫叔写的代码来找出来末尾是64的n了。上代码:
#include<stdio.h>
const int maxn=1e6+10;
int a[maxn];
int main()
{
int v=1;
for(int i=1;i<maxn-10;i++){
v=v*2%1000000;
if(v==64){
printf("%d %d\n",v,i);
}
a[v]++;
}
return 0;
}
(其实也不用找到1e6这么多)
很容易看出从第六位开始,每12500个数字一个循环,那这不就找到规律了吗?
已ac代码:
#include<stdio.h>
int main()
{
int n,m;
scanf("%d",&n);
int a[12510]={0,2,4,8,16,32};
for(int i=6;i<=12505;i++){
a[i]=a[i-1]*2%1000000;
}
while(n--){
scanf("%d",&m);
if(m<=12505){
printf("%d\n",a[m]-1);
}else{
m=(m-6)%12500+6;
printf("%d\n",a[m]-1);
}
}
return 0;
}
后记:
关于某个数的n次幂是都有规律的,好比3的末尾规律是3,9,7,1等等,所以这种方法不止可以解决2的次幂问题,其他的数字也是可以类比推出来的!
最后附上全程给予我帮助的卫叔的主页,希望看到这里的都去关注关注他!