题目链接:点击这里
题意: 给定x, 求最接近x的数p使得p分解后每一个质数出现两次.
每个质数出现两次说明是一个完全平方数, 所以要求一个最接近 x√ 的数使得这个数分解后每个质数出现一次. 显然质数本身就是一种可行解. 而两个质数之间又不会差的太远. 所以直接暴力枚举就好了.
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <algorithm>
#include <map>
#include <set>
using namespace std;
#define maxn 100005
#define INF 1e18
bool is_prime[maxn];
int prime[maxn], cnt;
void init () {
cnt = 0;
memset (is_prime, 1, sizeof is_prime);
is_prime[0] = is_prime[1] = 0;
for (int i = 2; i < maxn; i++) {
if (is_prime[i]) {
prime[cnt++] = i;
for (int j = i+i; j < maxn; j += i)
is_prime[j] = 0;
}
}
}
long long x;
bool ok (long long x) {
long long num = x;
for (int i = 0; i < cnt && 1LL*prime[i]*prime[i] <= num; i++) {
if (num%prime[i] == 0) {
int tmp = 0;
while (num%prime[i] == 0) tmp++, num/=prime[i];
if (tmp != 1)
return 0;
}
}
return 1;
}
long long solve (long long x) {
long long l = floor (sqrt (x));
long long r = ceil (sqrt (x));
long long ans = INF;
for (; ; l--) {
if (ok (l)) {
ans = min (ans, abs (x-l*l));
break;
}
}
for (; ; r++) {
if (ok (r)) {
ans = min (ans, abs (x-r*r));
break;
}
}
return ans;
}
int main () {
init ();
int t;
scanf ("%d", &t);
while (t--) {
scanf ("%lld", &x);
if (x <= 6) {
printf ("%lld\n", abs (x-4));
continue;
}
printf ("%lld\n", solve (x));
}
return 0;
}