HDU 5778 abs (暴力枚举)
abs
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Problem Description
Given a number x, ask positive integer y≥2, that satisfy the following conditions:
1. The absolute value of y - x is minimal
2. To prime factors decomposition of Y, every element factor appears two times exactly.
1. The absolute value of y - x is minimal
2. To prime factors decomposition of Y, every element factor appears two times exactly.
Input
The first line of input is an integer T ( 1≤T≤50)
For each test case,the single line contains, an integer x ( 1≤x≤1018)
For each test case,the single line contains, an integer x ( 1≤x≤1018)
Output
For each testcase print the absolute value of y - x
Sample Input
5
1112
4290
8716
9957
9095
Sample Output
23
65
67
244
70
描述:
给你一个long long范围的数x,然后让你找到一个数y,数y的质因数分解中,每个数刚好出现两次,输出的是abs(x-y)最小。
题解:
比赛的时候没想出来,后来看题解发现竟然这么水= =。
官方题解:由于y质因数分解式中每个质因数均出现2次,那么y是一个完全平方数,设y=z*z,题目可转换成求z,使得每个质因数出现1次. 我们可以暴力枚举z,检查z是否符合要求,显然当z是质数是符合
要求,由素数定理可以得,z的枚举量在logn级别 复杂度 O(\sqrt[4]{n}log\sqrt[2]{n}4√nlog2√n);
就只需要在x周围枚举就好了,枚举的范围题解说很小。。。然后z判断是不是满足条件的也很简单。
代码:
1 #include<cstdio> 2 #include<cmath> 3 #include<iostream> 4 #include<algorithm> 5 #include<vector> 6 #include<stack> 7 #include<cstring> 8 #include<queue> 9 #include<set> 10 #include<string> 11 #include<map> 12 #define inf 9223372036854775807 13 #define INF 9e7+5 14 #define PI acos(-1) 15 using namespace std; 16 typedef long long ll; 17 typedef double db; 18 const int maxn = 1e5 + 5; 19 const int mod = 1e9 + 7; 20 const db eps = 1e-9; 21 22 // 判断这个数满不满足条件。 23 bool ok(ll x) { 24 for (ll i = 2; i*i <= x; i++) { 25 int num = 0; 26 while (x % i == 0) { /*这里的i满足while的条件肯定是素数,为什么呢,就和素数筛选法的原理差不多。*/ 27 num++; 28 x /= i; 29 if (num > 1) return false;// 如果大约两次就不满足条件 30 } 31 } 32 return true; 33 } 34 35 ll abss(ll x) { 36 return x >= 0 ? x : -x; 37 } 38 39 void solve() { 40 ll n, ans; cin >> n; 41 ll z = sqrt(n+0.5D); 42 //cout << z << endl; 43 for (ll i = 0; ; i++) { 44 ll tmp = z + i; 45 if (tmp * tmp >= n && ok(tmp)) { /*因为不比比n小,所以要满足 >= n这个条件,测试样例的时候发现8开方是2,然后2是满足条件的,此时找到的答案就不对。*/ 46 ans = abss(tmp*tmp - n); 47 //cout << tmp << endl; 48 break; 49 } 50 } 51 for (ll i = 0; ;i++) { 52 ll tmp = z - i; 53 if (ok(tmp)) { 54 ans = min(ans, abs(tmp*tmp - n)); 55 break; 56 } 57 } 58 if (n < 4) ans = 4 - n; /*小于4的开方都是1,然后用ok函数判断的1是满足条件的,但是1不是素数,所以要特判。*/ 59 cout << ans << endl; 60 } 61 62 int main() 63 { 64 //cin.sync_with_stdio(false); 65 //freopen("isharp.in", "r", stdin); 66 //freopen("hh.txt", "w", stdout); 67 int t; cin >> t; 68 69 while (t--) 70 solve(); 71 return 0; 72 }