UVA 11549 CALCULATOR CONUNDRUM(Floyd判圈算法)

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 }
 
原文地址:https://www.cnblogs.com/acm-bingzi/p/3202896.html