UVA 11549 CALCULATOR CONUNDRUM(Floyd判圈演算法)

賈樹丙發表於2013-07-20

CALCULATOR CONUNDRUM
 

 

Alice got a hold of an old calculator that can display n digits. She was bored enough to come up with the following time waster.

She enters a number k then repeatedly squares it until the result overflows. When the result overflows, only the most significant digits are displayed on the screen and an error flag appears. Alice can clear the error and continue squaring the displayed number. She got bored by this soon enough, but wondered:

“Given n and k, what is the largest number I can get by wasting time in this manner?”

Program Input

The first line of the input contains an integer (1 ≤ ≤ 200), the number of test cases. Each test case contains two integers (1 ≤ ≤ 9) and (0 ≤ < 10n) where n is the number of digits this calculator can display is the starting number.

Program Output

For each test case, print the maximum number that Alice can get by repeatedly squaring the starting number as described.

Sample Input & Output

INPUT

2
1 6
2 99

OUTPUT

9
99

題目大意:計算器謎題。有一個老式計算器,只能顯示n位數字。有一天,你無聊了,於是輸入一個整數k,然後反覆平方,直到溢位。每次溢位時,計算器會顯示出結果的最高n位和一個錯誤標記。然後清除錯誤標記,繼續平方。如果一直這樣做下去,能得到的最大數是多少?比如,當n=1,k=6時,計算器將以此顯示6、3(36的最高位),9、8(81的最高位),6(64的最高位),3...

分析:題目已經暗示了計算器顯示出的數將出現迴圈。
  想象一下,假設兩個小孩在一個“可以無限向前跑”的跑道上賽跑,同時出發,但其中一個小孩的速度是另一個的2倍。如果跑道是直的,跑得快的小孩永遠在前面;但如果跑道有環,則跑得快的小孩將“追上”跑得慢的小孩。
  這個演算法稱為Floyd判圈演算法,不僅空間複雜度降為O(1),執行時間也將縮短到0.5秒。

程式碼如下:
 1 #include<iostream>
 2 using namespace std;
 3 
 4 int buf[10];
 5 
 6 int next(int n, int k) {
 7   if(!k) return 0;
 8   long long k2 = (long long)k * k;
 9   int L = 0;
10   while(k2 > 0) { buf[L++] = k2 % 10; k2 /= 10; } // 分離並儲存k2的各個數字
11   if(n > L) n = L;
12   int ans = 0;
13   for(int i = 0; i < n; i++) // 把前min{n,L}位重新組合
14     ans = ans * 10 + buf[--L];
15   return ans;
16 }
17 
18 int main() {
19   int T;
20   cin >> T;
21   while(T--) {
22     int n, k;
23     cin >> n >> k;
24     int ans = k;
25     int k1 = k, k2 = k;
26     do {
27       k1 = next(n, k1); // 小孩1
28       k2 = next(n, k2); if(k2 > ans) ans = k2; // 小孩2,第一步
29       k2 = next(n, k2); if(k2 > ans) ans = k2; // 小孩2,第二步
30     } while(k1 != k2); // 追上以後才停止
31     cout << ans << endl;
32   }
33   return 0;
34 }

 

 

相關文章