hdu 5778

题意:

给定一个数x,求正整数y≥2y\geq 2y2,使得满足以下条件:

1.y-x的绝对值最小

2.y的质因数分解式中每个质因数均恰好出现2次。

思路:

开根号上下搜索,枚举素数的方,判断是否成立,题目数据1e18,开根1e9,故判断是否包含素数方只需要枚举4*1e4内的素数就够了,完全在可解范围之内;

 

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <math.h>
#include <cstdio>
#include <cstring>
#include <string>
#include <string.h>
#include <vector>
#include <queue>
#include <map>
#include <set>

using namespace std;
#define ll long long
const long long inf=(ll)1e15+88;

const int maxn=(int)1e4+88;
const int mod=1000000007;

ll a[maxn];
bool ab(ll mid)
{
    for(int i=2;i<maxn;i++)
    {
        if(a[i]==0&&mid%(i*i)==0)
            return false;
    }
    return true;
}
ll myabs(ll a)
{
    if(a>0)return a;
    return -a;
}
int main()

{
//    freopen("1010.in", "r", stdin);
//     freopen("out.txt", "w", stdout);
    for(int i=0;i<maxn;i++)
        a[i]=0;
    for(int i=2;i<maxn;i++)
    {
        if(a[i]!=0)continue;
        for(int q=2;i*q<maxn;i++)
        {
            a[i*q]=1;
        }
    }
    int t;
    cin>>t;
    while(t--)
    {
        ll n;
        cin>>n;
        if(n<=4)cout<<4-n<<endl;//因为最小素数方为4,小于4向前搜索没意义,故特判
        else {
        ll m=(ll)sqrt(n);
        ll l=m,r=m;

        for(l;l>=2;l--)//开根向下去整
        {
            if(ab(l))
                break;
        }
        for(++r;r;r++)//因为开根强转相当于开根向下取整,在其下,r需在其上,++r正好包含
        {
            if(ab(r))
                break;
        }

        cout<<min(myabs(n-l*l),myabs(r*r-n))<<endl;
        }
    }
    return 0;
}

    注意:n之内的合数总可以通过根号n的区间来求解!!!时间复杂度即可降!!!

 

 

 

 

 

 




posted @ 2016-08-01 11:42  热风轻浮  阅读(206)  评论(0)    收藏  举报