題目大意:
有t(1<=t<=200)組數據
有一個老計算器只能顯示n(1<=n<=9)位數字,有一天無聊了就輸入一個整數k(k在顯示範圍內且大於等於0)然後一直平方,直到溢出。每次溢出時,會顯示出結果的最高n位,然後用這n位繼續平方。如果這樣一直做下去,能得到的最大數是多少?
只能顯示n位,所以能出來的數一定是有限的,但是應該不能取到區間裏的所有數
也就是說一直平方會陷入到一個循環裏去,我們只要挑出這個循環裏的最大的數
問題也就主要是怎麼判是否進入了循環
先想到的必然是開一個10^9+1的bool數組。。。
但是應該開不出來吧
那就可以用哈希表,開一個小一些的數組
不過要防止碰撞。。。又要設計hash函數
那麼,我們就可以用Floyd判圈算法
想象兩個人在一個環形跑道上跑步,一個人跑的比較快,一個人跑的比較慢
那麼快的人最終就會“追上”慢的人
這就是算法的主題思想
可以依照這種思想,設置兩個變量,一個每次平方兩次,一個每次平方一次,如果他們相等了,說明快的已經循環了一圈了
這樣就可以把空間複雜度降到O(1)
代碼
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#define For(i,l,r) for(int i=l;i<=r;++i)
using namespace std;
long long k,w1,w2,m[10]={1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000},ans;
int n;
bool flag;
void next1()
{
ans=max(ans,w1);
w1*=w1;
while(w1>=m[n])
w1/=10;
if(w1==w2)
flag=1;
ans=max(ans,w1);
}
void next2()
{
w2*=w2;
while(w2>=m[n])
w2/=10;
if(w1==w2)
flag=1;
}
int main()
{
int t;
scanf("%d",&t);
For(i,1,t)
{
flag=0;
ans=-1;
scanf("%d %lld",&n,&k);
w1=k;w2=k;
while(1)
{
next1();
next1();
next2();
if(flag)
{
printf("%lld\n",ans);
break;
}
}
}
return 0;
}