MYF

HDU 5778 abs

题目链接

HDU 5778

题目类型:数论

题目来源:BestCoder #85

题目分析

题目大意

给出一个n,找出离n最近的一个数x,使x是若干个质数平方的乘积,求abs(x-n)

解析

由于x为若干个质数平方的乘积,那么x必然为平方数,所以我们就可以直接找sqrt(n)附近,唯一分解定理所分解出来的各质因数指数为1的数。很容易想到打素数表,然后枚举所有大于sqrt(n)和小于sqrt(n)的数,找到第一个符合条件的即可。因为1e5内的素数还是比较少的,所以这个做法并不会太慢。

代码

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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <set>
#include <map>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <string>
#include <vector>
#include <iomanip>
#include <bitset>
#include <cstring>
#include <iostream>
#include <deque>
#include <algorithm>
#define Memset(a,val) memset(a,val,sizeof(a))
#define PI acos(-1)
#define PB push_back
#define MP make_pair
#define rt(n) (i == n ? '\n' : ' ')
#define hi printf("Hi----------\n")
#define IN freopen("input.txt","r",stdin);
#define OUT freopen("output.txt","w",stdout);
#define debug(x) cout<<"Debug : ---"<<x<<"---"<<endl;
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int maxn=100000+5;
const int mod=1000000007;
const int INF=0x3f3f3f3f;
const double eps=1e-8;
ll prime[maxn]={1};
int pcnt=0;//素数下标1~pcnt-1
ll factor[maxn]={1,1}; //factor[i]表示i的最小质因子
void Init_Prime(){
pcnt=1;
for(ll i = 2 ; i < maxn ; i ++){
if(!factor[i]) {
prime[pcnt++]=i;
factor[i]=i;
}
for(ll j = 1 ; j < pcnt && i * prime[j] < maxn ; j ++)
{
factor[i * prime[j]] = prime[j];
if( !(i % prime[j] ) )
break;
}
}
return;
}
bool judge(ll x){
for (int i=1; i<=pcnt&&prime[i]*prime[i]<x; i++) {
if (x%prime[i]==0) {
x/=prime[i];
if (x%prime[i]==0) {
return false;
}
}
}
return true;
}
int main(){
Init_Prime();
int T;
scanf("%d",&T);
while (T--) {
ll x;
cin>>x;
ll up = sqrt(x);
ll down = up;

while (up*up<x) up++;
while (!judge(up)) up++;
up = max(2LL, up);

while (down*down>x) down--;
while (!judge(down)) down--;
down = max(2LL, down);

ll ans =min(abs(x-down*down), abs(x-up*up));

cout<<ans<<endl;
}
}