具体来说,当盘数大于一时,不违背原则下(过程中总是大在下小的在上),A先借助B再放到C上。总是把盘数看成两个来解决问题。
比如说,当盘数为二时,顾名思义,这个很简单只要三下即可完成。这个时候,可以这样想,如果是三个,就相当于二个完成,还有一个待完成,(注意要有把问题简化为两个盘的思想,这样是递归思想的思想实现),那么把完成的看成一个,剩下待完成的看成一个(带完成的还可以把最近要完成的看成一个,剩下的先别管),这样问题就回到了二个盘数时的第一步完成状态,然后C上的(二个看成一个)在借助B放到A上,这样第三个就可以从B放到C上,接下来又是二个了(这个是真正的二个),看基本步骤完成。当盘数是N时,也是利用这种思想,一步一步简化,递归完成。
接下来谈一下N个盘要几次完成:
当完成n个时设用M(n)次,那么,如上说的算法当完成n个(也就是n+1个时了)还有一个,这时需要把在C上的看成一个,借助B移动到A上(这时最后一个已到B上),当然要做M(n)次搬动了,完成后,B上的最后一个((n+1)个)搬动到C上。这时,问题又回到了n次开始,当然需要M(n)次了。这么一来就是M(n)*2次,加上最后一个的两次,总共是M(n)*2+2=M(n+1)次,好了现在是纯数学问题了,结果是M(n)=2^n-1.
方法一:
#include<iostream>
using namespace std;
long long g(int a,int b)
{
int x,y;
if(b==0)
return 1;
if(b==1)
return 2;
x=g(a,b/2);
y=(long long)x*x%1000000;
if(b%2==1)
y=y*2%1000000;
return (int)y;
}
int main()
{
int n,t;
long long m;
cin>>n;
while(n--)
{
cin>>m;
t=g(2,m);
cout<<t-1<<endl;
}
return 0;
}
方法二:
- #include<stdio.h>
- int main()
- {
- int i,j,k,l,m,n,s;
- scanf("%d",&s);
- while(s--)
- {
- int c=1;
- scanf("%d",&n);
- if(n>12500)//对输入的数据进行处理
- {
- if(n%100000<6)
- n=n%10+100000;
- else n%=100000;
- }
- while(n--)
- {
- c=2*c;
- c%=1000000;
- }
- printf("%d\n",c-1);
- }return 0;
- }
方法三:
- #include<stdio.h>
- int a[100006];
- int main()
- {
- int s,m,i;
- a[1]=1;
- for(i=2;i<100006;i++)
- {
- a[i]=(2*a[i-1]+1)%1000000;
- }
- scanf("%d",&s);
- while(s--)
- {
- scanf("%d",&m);
- if(m>12500)
- {
- if(m%100000<6)
- m=100000+m%10;
- else
- m%=100000;
- }
- printf("%d\n",a[m]);
- }
- return 0;
- }