https://vjudge.net/problem/UVA-11549
题意:
有一个老式计算器,只能显示n位数字。输入一个整数k,不断地平方,直到溢出。每次溢出的时候,会不断的显示最高n位和错误标记,之后错误标记会清除,继续平方。求在这个过程中出现的最大的数字。
思路:
首先,手算了几个例子,发现最后会产生循环,于是我就用map记录每个数字的出现,直到出现重复为止,然后输出map中的最大值。
代码:
1 #include <stdio.h> 2 #include <map> 3 using namespace std; 4 typedef long long ll; 5 map<ll,bool> mmp; 6 7 ll mpow(int b,int n) 8 { 9 if (n == 0) return 1; 10 11 long long ans = mpow(b, n / 2); 12 13 ans *= ans; 14 15 if (n & 1) ans *= b; 16 17 return ans; 18 } 19 20 int cal(long long k) 21 { 22 int cnt = 0; 23 24 while (k) 25 { 26 k /= 10; 27 cnt++; 28 } 29 30 return cnt; 31 } 32 33 int main() 34 { 35 int t; 36 37 scanf("%d",&t); 38 39 while (t--) 40 { 41 mmp.clear(); 42 43 int n; 44 long long k; 45 46 scanf("%d%lld",&n,&k); 47 48 49 50 long long m = mpow(10,n); 51 52 if (k == 0) 53 { 54 printf("0 "); 55 56 continue; 57 } 58 59 if (k == 1) 60 { 61 printf("1 "); 62 63 continue; 64 } 65 66 67 while (1) 68 { 69 if (k == 1 || mmp[k]) break; 70 71 mmp[k] = 1; 72 73 k *= k; 74 75 int cnt = cal(k); 76 77 if (cnt <= n) continue; 78 79 k /= mpow(10,cnt - n); 80 81 //printf("%lld * ",k); 82 } 83 84 printf("%lld ",mmp.rbegin()->first); 85 } 86 87 return 0; 88 }
之后看到了lrjjj的做法,用了一个叫做floyd判圈法的方法,就是在一个环形跑道上,两个小孩子跑步,一个孩子的速度是另外一个的两倍,那么如果同时出发的话,快的孩子会超越慢的孩子,并在某一时刻两人会相遇。
这题呢,就是一个循环,那么定义两个起始的数,一个每次变换一次,一个每次变换两次,那么两个数相等的时候就可以跳出循环,一个循环当中的所有数字肯定都遍历完了。这个方法主要是有着优秀的空间复杂度为O(1)。
但是它的时间复杂度也比用map优秀:
这是用floyd判圈法做的
这是用map做的
代码:
1 #include <stdio.h> 2 3 long long mpow(long long b,int n) 4 { 5 if (n == 0) return 1; 6 7 long long ans = mpow(b,n / 2); 8 9 ans *= ans; 10 11 if (n & 1) ans *= b; 12 13 return ans; 14 } 15 16 int cal(long long k) 17 { 18 int cnt = 0; 19 20 while (k) 21 { 22 cnt++; 23 k /= 10; 24 } 25 26 return cnt; 27 } 28 29 long long nex(long long k,int n) 30 { 31 k *= k; 32 33 int cnt = cal(k); 34 35 if (cnt <= n) return k; 36 37 k = k / mpow(10,cnt - n); 38 39 return k; 40 } 41 42 int main() 43 { 44 int t; 45 46 scanf("%d",&t); 47 48 while(t--) 49 { 50 int n; 51 long long k; 52 53 54 scanf("%d%lld",&n,&k); 55 56 long long ans = k; 57 58 long long k1 = k,k2 = k; 59 60 do 61 { 62 k1 = nex(k1,n);if (k1 > ans) ans = k1; 63 k2 = nex(k2,n);if (k2 > ans) ans = k2; 64 k2 = nex(k2,n);if (k2 > ans) ans = k2; 65 66 }while (k1 != k2); 67 68 printf("%lld ",ans); 69 } 70 71 return 0; 72 }