NUOJ 88
思路1:
找规律,本题若是直接暴力搜索,就是f(n)=2^n-1,然后f(n)%1000000,那么结果会越界;所以考虑用f(n+1)=(2*f(n)+1)%1000000,不过遇到较大数据的时候,会出现超时的情况,毕竟这个结果是线性时间增长的,和输入数据体量的大小有直接关系,所以这里还需要再次考虑优化。通过数据对比发现,当n>10005时,有f(123456)=f(23456) f(123456789)=f(23456789)=...=f(56789) 即略去高位,剩下五位数。但是还需要考虑的是 if(m%100000<6),需要有m=100000+m%10;如此处理之后就不会超时了。
1 #include <iostream> 2 using namespace std; 3 4 int num[100006]; 5 int main(){ 6 int N,m,i; 7 num[1]=1; 8 for(int i=2;i<100006;i++){ 9 num[i] = (2*num[i-1]+1)%1000000; 10 } 11 cin>>N; 12 while(N--){ 13 cin>>m; 14 if(m>100005){ 15 if(m%100000<6 ){ 16 m = 100000+m%10; 17 } 18 else{ 19 m = m%100000; 20 } 21 } 22 cout<<num[m]<<endl; 23 } 24 25 }
思路2:
我们知道汉诺塔的公式是f(n)=2^n-1
而f(n)%1000000= (2^n-1)%1000000 = 2^n%100000-1
而2^n%1000000可以用快速幂算法计算,代码如下:
1 #include <iostream> 2 using namespace std; 3 4 long long fastmod(long long a,long long b,long long c){ 5 long long num=1; 6 a%=c;//这里不进行初始化也是可以的 7 8 while(b>0){ 9 if(b%2==1){ 10 num=(num*a)%c; 11 } 12 b/=2; //这一步将b->log2(b) 13 a=(a*a)%c; 14 } 15 return num; 16 } 17 18 int main(){ 19 int n; 20 cin>>n; 21 while(n--){ 22 long long m; 23 cin>>m; 24 cout<<fastmod(2,m,1000000)-1<<endl; 25 } 26 }