NYOJ 88 汉诺塔(一)
地址:http://acm.nyist.net/JudgeOnline/problem.php?pid=88
思路1:
对于汉诺塔求移动次数公式为f(n+1)=f(n)*2+1;
此题如果用要求十进制最后六位,f(n+1)=(f(n)*2+1)%100000;
每次输入层数,求出移动次数,但如果输入数据很大,利用此公式必定超时,经过多次测试,发现若输入数据大于100005,有如下规律,如:
f(123456)=f(23456); f(123456789)=f(23456789)---=f(56789)
即略去最高位,
但 if(m%100000<6)则需进行此操作 m=100000+m%10;
这样就不会超时了
1 #include<stdio.h> 2 int num[100006]; 3 int main() 4 { 5 int N,m,i; 6 num[1]=1; //只有一个的情况 7 for(i=2;i<100006;i++) 8 num[i]=(2*num[i-1]+1)%1000000; 9 scanf("%d",&N); 10 while(N--) 11 { 12 scanf("%d",&m); 13 if(m>100005) 14 { 15 if(m%100000<6) 16 m=100000+m%10; 17 else 18 m%=100000; 19 } 20 printf("%d\n",num[m]); 21 } 22 return 0; 23 }
思路2:快速模幂法
1 #include<iostream> 2 #include<cmath> 3 using namespace std; 4 5 long long pow_mod(long long n) 6 { 7 if(n==1) return 2; 8 long long t; 9 t=pow_mod(n/2); 10 if(n%2==0) 11 { 12 return ((t%1000000)*(t%1000000))%1000000; 13 } 14 else 15 { 16 return (2*(t%1000000)*(t%1000000))%1000000; 17 } 18 } 19 20 int main() 21 { 22 int test; 23 long long n; 24 cin>>test; 25 while(test--) 26 { 27 cin>>n; 28 cout<<pow_mod(n)-1<<endl; 29 } 30 return 0; 31 }