问题描述
给定一个数x,求正整数y≥2y\geq 2y≥2,使得满足以下条件: 1.y-x的绝对值最小 2.y的质因数分解式中每个质因数均恰好出现2次。 输入描述 第一行输入一个整数T(1≤T≤501\leq T\leq 501≤T≤50) 每组数据有一行,一个整数x(1≤x≤10181\leq x\leq {10}^{18}1≤x≤1018) 输出描述 对于每组数据,输出一行y-x的最小绝对值 输入样例 5 1112 4290 8716 9957 9095 输出样例 23 65 67 244 70
思路:
因为每个质因子恰好出现两次,所以可以开平方到10的9次,10的9次方内的数相邻两质数距离不超过三百,因为质数是肯定满足条件的所以答案就在距离x最近的两相邻质数区间内。这样只需前后暴力排除就行,注意往前找的时候有停止范围(1),排除的方法是素数打表,挨个排...
代码:
#include <iostream> #include <cstdio> #include <string> #include <cstring> #include <algorithm> #include <cmath> #define MAX_N 100000 + 1 using namespace std; typedef __int64 LL; int h; LL prime[MAX_N]; ///第i个素数 bool is_prime[MAX_N + 1];/// is_prime[i]为true表示i为素数 // 返回n以内素数的个数 int sieve(int n) { int p = 0; for(int i = 2; i <= n; i++) is_prime[i] = true; is_prime[0] = is_prime[1] = false; for(int i = 2; i <= n; i++) { if(is_prime[i]) { prime[p++] = i; for(int j = 2*i; j <= n; j += i) is_prime[j] = false; } } return p; } bool operat(int n) { for(int i = 0; i < h && 1LL*prime[i]*prime[i]<=n; i++) if(n%(1LL*prime[i]*prime[i])==0) //说明该数的因子中至少有两个prime[i]; return false; return true; } int main() { int n; cin>>n; h = sieve(40000); while(n--) { long long x,x1,y1; scanf("%I64d",&x); long long xx = 1LL*sqrt(x*1.0); for(x1 = xx; x1 >= 2; x1--) if(operat(x1)) break; for(y1 = xx+1;;y1++) if(operat(y1)) break; if(x1 >= 2) printf("%I64d\n",min(x-x1*x1,y1*y1-x)); else printf("%I64d\n",y1*y1-x); } return 0; }