很容看出来,一直平方又只取前面n位会构成循环,所以可以模拟,判重的话就用hash
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
const int maxn = 5000;
vector<int>hash1[maxn];
bool vis(int h){
int t = h;
h = h % maxn;
for(int i = 0; i < hash1[h].size(); ++i){
if(t == hash1[h][i])return true;
}
hash1[h].push_back(t);
return false;
}
int main(){
int T, k, n;
scanf("%d", &T);
while(T--){
scanf("%d %d", &k, &n);
int ans = n;
for(int i = 0; i < maxn; ++i){
hash1[i].clear();
}
char num[20];
while(!vis(n)){
long long tmp = (long long)n * n;
int m = 0;
while(tmp){
num[m++] = tmp % 10 + '0';
tmp /= 10;
}
n = 0;
for(int i = m - 1, j = k; j && i >= 0; --j, --i){
n = n * 10 + (num[i] - '0');
}
ans = max(ans, n);
}
printf("%d\n", ans);
}
return 0;
}
训练指南上还有一种做法,不用判重,称为floyd判圈法,但是速度比hash的慢一点.
想象下假设有两个小孩在一个"可以无限向前跑"的跑道上赛跑,同时出发,但是其中一个小孩的速度一直是另一个的两倍。如果跑道是值的,那么第一个小孩永远跑在最前.但是如果有环,则第一个小孩先跑到了环中,则一直在环中跑,直到后面的小孩也跑到了环里,因为第一个小孩的速度是第二个小孩的两倍,所以两个小孩迟早碰到(结束条件).
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
int k, n;
int next(int n){
char num[20];
long long tmp = (long long)n * n;
int m = 0;
while(tmp){
num[m++] = tmp % 10 + '0';
tmp /= 10;
}
n = 0;
for(int i = m - 1, j = k; j && i >= 0; --j, --i){
n = n * 10 + (num[i] - '0');
}
return n;
}
int main(){
int T;
scanf("%d", &T);
while(T--){
scanf("%d %d", &k, &n);
int ans = n;
int k1 = n, k2 = n;
do{
k1 = next(k1);
//两倍速度
k2 = next(k2);
ans = max(ans, k2);
k2 = next(k2);
ans = max(ans, k2);
}while(k1 != k2);
printf("%d\n", ans);
}
return 0;
}