思路
由于y质因数分解式中每个质因数均出现2次,那么y是一个完全平方数,设y=z*z,题目可转换成求z,使得每个质因数出现1次. 我们可以暴力枚举z,检查z是否符合要求,显然当z是质数是符合要求,由素数定理可以得,z的枚举量在logn级别 
感受
这道题一开始做的时候我知道我是处理不了10^18的数据的,只是死马当活马医,竟然好让我给AC了,当然最后还是送了别人50分的hack。后来是看了学长的代码,思考了很久,发现自己有三个地方写的不行,数感也不敏锐。在聪明的卓君的帮助下终于是理解,为什么10^5的prime数组就能解决10^18数据。
数学证明
1 2 3 4 5 6 7 8 9 
  | bool judg(ll x){ 	for(int i=1;i<=cnt && ned[i] * ned[i] <=x;i++){ 		if(x%ned[i]==0){ 			x/=ned[i]; 			if(x%ned[i]==0)return 0; 		} 	} 	return 1; } 
  | 
 
设100007是大于10^5最小的素数。则100007100007是不符合条件但是上面代码是return 1的。
可是别忘了,我们之前开根号过,所以我们还原数据,平方一下得100007100007100007100007 > 10^20
超出了数据范围,所以在数据范围里是不可能有特例的。
好筛法
1 2 3 4 5 6 7 8 9 10 11 
  | void isprime(){ 	cnt=0 	for(int i=0 	for(ll i=2 		if(prime[i])ned[++cnt]=i 		for(ll j=1; j<=cnt && i*ned[j] <= maxn  				prime[i * ned[j]] = 0 				if(i % ned[j] == 0)break; 		} 	} } 
  | 
 
AC代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 
  | #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define eps 1e-10 #define ll long long  #define maxn 100005 bool prime[maxn]; ll ned[maxn],cnt; void isprime(){ 	cnt=0; 	for(int i=0;i<maxn;i++) prime[i]=1; 	for(ll i=2;i<maxn;i++){ 		if(prime[i])ned[++cnt]=i; 		for(ll j=1; j<=cnt && i*ned[j] <= maxn ;j++){ 				prime[i * ned[j]] = 0; 				if(i % ned[j] == 0)break; 		} 	} } bool judg(ll x){ 	for(int i=1;i<=cnt && ned[i] * ned[i] <=x;i++){ 		if(x%ned[i]==0){ 			x/=ned[i]; 			if(x%ned[i]==0)return 0; 		} 	} 	return 1; } int main() { 	isprime(); 	int n; 	cin>>n; 	while(n--){ 		ll x,ans1,ans2; 		scanf("%I64d",&x); 		ll tmp=sqrt(x*1.0); 		bool left=0,right=0; 		for(ll i=1; ;i++) 		{ 			if(left==0 && judg(tmp-i+1)){ 				if(2 > (tmp-i+1)) ans1=abs(4-x); 				else ans1=abs((tmp-i+1)*(tmp-i+1)-x); 				left = 1; 			} 			if(right==0 && judg(tmp+i) ){ 				if(2 > (tmp+i)) ans2=abs(4 - x); 				else ans2=abs((tmp+i)*(tmp+i)-x); 				right = 1; 			} 			if(left && right) break; 		} 		printf("%I64d\n",min(ans1,ans2)); 	}    return 0; } 
  |