UVA11549 Calculator Conundrum 計算器謎題(Floyd判圈)

題目描述

PDF

輸入輸出格式

輸入格式:

輸出格式:

輸入輸出樣例

輸入樣例#1: 複製
2
1 6
2 99
輸出樣例#1: 複製
9
99




題目大意:
有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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章