1. 程式人生 > >UVa11549:Calculator Conundrum

UVa11549:Calculator Conundrum

spa 答案 訓練指南 快的 str tdi class 所有 跑步

UVa11549:Calculator Conundrum

題目大意

有一個老舊的計算器只能顯示前n個數字。現在給定一個數字k,每次給k平方,如果答案長度超過n則從最高位開始顯示n個數字,丟棄其余數字。

要求:求出計算器能顯示的最大數字。

Solution1(naive)

本題中得到的數列會出現循環,可以用一個set記錄所有得到的數字,一旦出現重復數字停止循環,輸出set中的最大值即可。

AC-Code(C++)

Time:540ms

#include <iostream>
#include <iomanip>
#include <algorithm>
#include <string>
#include <cstring>
#include <map>
#include <set>
#include <vector>
#include <cmath>
#include <climits>
#include <ctime>

using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1.0);
const int maxn = 30000 + 10;

/*
 * 劉汝佳 訓練指南 P42
 */

int n,k,mask;

int getNext(int x){
    ll temp = (ll)x * x;
    while(temp >= mask)
        temp /= 10;
    return (int)temp;
    
}

int main(int argc, const char * argv[]) {
    
//    freopen("input.txt", "r", stdin);
    
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d %d",&n,&k);
        mask = 1;
        for(int i=0;i<n;i++)
            mask *= 10;
        
        set<int> s;
        int ans = k;
        while(s.count(k)==0){
            s.insert(k);
            k = getNext(k);
            ans = max(ans,k);
        }
        
        printf("%d\n",ans);
        
    }
    
    
    return 0;
}

Solution2(floyd判圈法)

想象兩個人賽跑,兩人以不同的速度勻速運動。如果賽道是直線的,那麽兩個人以後再也不會相遇了,而如果兩個人在一個環形賽道上跑步,那麽速度快的那個人一定會在某一時刻從後面追上速度慢的那個人。

在這裏循環的序列就是環形賽道,這種方法叫做floyd判圈法,這樣做後因為不需要頻繁的在set中查詢元素是否存在,所以運行速度有了很大的提升,並且還將空間復雜度降為Ο(1)。

Note

在判圈的時候最開始我很順的寫出了如下代碼,但這樣會造成個別點沒有取到就退出循環了,所以某些測試例子中的出的答案往往要比正確答案稍微小一點。

// wrong
do{
    k1 = getNext(k1);
    k2 = getNext(getNext(k2));
    ans = max(ans,max(k1,k2));
}while(k1 != k2);

AC-Code(C++)

Time:50ms

#include <iostream>
#include <iomanip>
#include <algorithm>
#include <string>
#include <cstring>
#include <map>
#include <set>
#include <vector>
#include <cmath>
#include <climits>
#include <ctime>

using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1.0);
const int maxn = 30000 + 10;

int n,k,mask;

/*
 * 劉汝佳 訓練指南 P42
 */

int getNext(int x){
    ll temp = (ll)x * x;
    while(temp >= mask)
        temp /= 10;
    return (int)temp;
    
}

int main(int argc, const char * argv[]) {
    
//    freopen("input.txt", "r", stdin);
    
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d %d",&n,&k);
        mask = 1;
        for(int i=0;i<n;i++)
            mask *= 10;
        
        int k1 = k;
        int k2 = k;
        int ans = k;
        // wrong
//        do{
//            k1 = getNext(k1);
//            k2 = getNext(getNext(k2));
//            ans = max(ans,max(k1,k2));
//        }while(k1 != k2);
        // right
        do{
            k1 = getNext(k1);
            k2 = getNext(k2);
            ans = max(ans,k2);
            k2 = getNext(k2);
            ans = max(ans,k2);
        }while(k1 != k2);

        printf("%d\n",ans);
        
    }
    

    return 0;
}



UVa11549:Calculator Conundrum