HDU5778 绝对值abs

【问题描述】

给定一个数 x,求正整数 y≥2,使得满足以下条件:
1.y-x 的绝对值最小;
2.y 的质因数分解式中每个质因数均恰好出现 2 次。

【输入数据】

第一行输入一个整数 T(1≤T≤50)
每组数据有一行,一个整数 x(1≤x≤10^18)

【输出数据】

对于每组数据,输出一行 y-x 的最小绝对值。

【输入样例 1】

5
1112
4290
8716
9957
9095

【输出样例 1】

23
65
67
244
70

【数据范围】

对于 20% 的数据, T = 1, x ⩽ 10^4
对于 50% 的数据, T ⩽ 10, x ⩽ 10^12
对于 70% 的数据, T ⩽ 30, x ⩽ 10^15
对于 100% 的数据, T ⩽ 50, x ⩽ 10^18
———————————————分割の线——————————————————————

【分析】

给定x求y,并且y给定了一定的条件。利用此条件求出使|x-y|最小的y值.
让我们分析一下这两个(半)条件:

  1. 取y使|x-y|的值最小是显而易见的。

  2. y中分解的每个质因数只出现两次:
    此处可以推得:y是一个完全平方数,开平方后仅由质数组成,且每个质数只出现一次(开方后不含平方数因子)。
    代码实现时,可以先枚举i,使得i*i==y。这时需要检验,i是否含有平方数因子。可以定义变量j,从2枚举到sqrt(i)判断是否存在j*j是i的因数。
    code

bool check(long long i)
{
    long long large=(long long)sqrt(i),j=2;
    while(j<=large)
    {
        if(i%(j*j)==0) return 0;
        j++;
    }
    return 1;
}

剩下的半个条件是y>=2其实就是特判,

    if(x<=4)
    {
        printf("%d\n",4-x);
        continue;
    }

完整代码如下:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
long long T,x;
bool check(long long x)
{
    long long large=(long long)sqrt(x),i=2;
    while(i<=large)
    {
        if(x%(i*i)==0) return 0;
        i++;
    }
    return 1;
}//判断是否存在完全平方因子
int main()
{
    freopen("abs.in","r",stdin);
    freopen("abs.out","w",stdout);
    cin>>T;
    for(int i=1;i<=T;i++)
    {
        scanf("%lld",&x);
        if(x<=4)
        {
            printf("%lld\n",4-x);
            continue;
        }//特判
        long long a=(long long)sqrt(x),j1,j2,ans;
        j1=a,j2=a+1;//分头枚举y的平方根
        while(j1>=2)
        {
            if(check(j1))break;
            else j1--;
        }//枚举y的下限
        while(j2<=x)
        {
            if(check(j2))break;
            else j2++;
        }//枚举y的上限
        ans=min(abs(j2*j2-x),abs(j1*j1-x));//比较哪个y可以使|x-y|最小
        printf("%lld\n",ans);
    }
    return 0;
}

写的不好,如有纰漏,请在下方评论区指出。

猜你喜欢

转载自blog.csdn.net/xyc1719/article/details/80301774