似乎没有什么技术含量,没有按照佳哥的写,直接用了log10的方法求位数,时间开销是1.5,如果按位数处理肯定更快,但是代码就要复杂很多。但是应用floyd判圈算法更快。
Floyd判圈算法
可以抽象成为两个小孩跑步,但是一个小孩的速度是另一个小孩的两倍,当跑的快的小孩追上跑的慢的小孩的时候,算法结束。此外,时间复杂度为 $O(1)$ 也是格外炫酷。
一个next一次,另一个next两次,很快便可以追上。
可能提出疑问:
既然肯定又重复的地方,为啥不让第一个小孩就在那里等呢?因为算法运行结果不一定是在小孩等的地方结束,可能还没有跑进圈里!
复杂AC
c
#include <cstdio> #include <cstring> #include <algorithm> #include <set> #include <cmath> using namespace std; #define lln long long lln n, k; int main() { int T; lln mm, temp; scanf("%d", &T); while(T--) { scanf("%lld%lld", &n, &k); mm = k; set <lln> s; s.clear(); lln div = pow(10, n); while(!s.count(k)) { s.insert(k); temp = k * k; if(temp >= div) { int digit = log10(temp) +1; lln mod = pow(10, digit - n); k = temp / mod; // k = temp / (lln)pow(10, digit); } else k = temp; mm = max(mm, k); } printf("%lld\n", mm); } return 0; }
floyd判圈
速度飞快,0.5
c
#include <cstdio> #include <iostream> using namespace std; #define lln long long int buf[10]; int next(int n, int k) { if(!k) return 0; lln k2 = (lln) k * k; int L = 0; while(k2 > 0) { buf[L++] = k2 %10; k2 /= 10; } if(n > L) n = L; int ans = 0; for(int i = 0; i < n;i ++) ans = ans * 10 + buf[--L]; return ans; } int main() { int T; cin >> T; while(T--) { int n, k; cin >> n >> k; int ans = k; int k1 = k, k2 = k; do { k1 = next(n, k1); k2 = next(n, k2); if(k2 > ans) ans = k2; k2 = next(n, k2); if(k2 > ans) ans = k2; } while(k1 != k2); cout << ans << endl; } return 0; }
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。