BestCoder Round #85 hdu5778 abs(素数筛+暴力)

abs

题意:

问题描述
给定一个数x,求正整数y,使得满足以下条件:
1.y-x的绝对值最小
2.y的质因数分解式中每个质因数均恰好出现2次。
输入描述
第一行输入一个整数T
每组数据有一行,一个整数x
输出描述
对于每组数据,输出一行y-x的最小绝对值
输入样例
5
1112
4290
8716
9957
9095
输出样例
23
65
67
244
70

题解:

由于y质因数分解式中每个质因数均出现2次,那么y是一个完全平方数,设y=z*z,题目可转换成求z,使得每个质因数出现1次. 我们可以暴力枚举z,检查z是否符合要求,显然当z是质数是符合要求,由素数定理可以得,z的枚举量在logn级别 。

上面是官方题解,再说我的理解:首先看范围是1e18,不好弄,但题里又说y的质因子出现2次,故想到要根号降到1e9,这样就可以素数筛 根号1e9 内的素数了,这样就可以判断在1e9内某个数是否为素数了。之后枚举就好了,题里说y-x的绝对值,所以前后都枚举,有一个符合条件的记录,然后break就好了,PS:向前枚举到2就可以了,因为题里说y>=2。

再说下怎么判断z,也就是我写的ok函数,就直接把 根号1e9 内素数循环一次就好了,如果可以取余0 就/=,之后在判断这个是否还是取余0,如果还是就不符合,因为要求z的质因数都只出现1次。当最后/=为1的时候就可以返回真了,最后如果一次取余==0都没有,就证明这是素数,所以也返回真。

代码:

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int INF=0x3f3f3f3f;
const ll LINF=0x3f3f3f3f3f3f3f3f;
#define PU puts("");
#define PI(A) cout<<A<<endl
#define SI(N) cin>>N
#define SII(N,M) cin>>N>>M
#define cle(a,val) memset(a,(val),sizeof(a))
#define rep(i,b) for(int i=0;i<(b);i++)
#define Rep(i,a,b) for(int i=(a);i<=(b);i++)
#define reRep(i,a,b) for(int i=(a);i>=(b);i--)
#define dbg(x) cout <<#x<<" = "<<x<<endl
#define PIar(a,n) rep(i,n)cout<<a[i]<<" ";cout<<endl;
#define PIarr(a,n,m) rep(aa,n){rep(bb, m)cout<<a[aa][bb]<<" ";cout<<endl;}
const double EPS= 1e-9 ;

/*  /////////////////////////     C o d i n g  S p a c e     /////////////////////////  */

const int MAXN= 40000 + 9 ;

int prime[MAXN],K;
bool is_prime[MAXN];
int sieve(int n)
{
    int p=0;
    for (int i=0;i<=n;i++) is_prime[i]=true;
    is_prime[1]=is_prime[0]=false;
    for (int i=2;i<=n;i++)
    {
        if (is_prime[i])
        {
            prime[p++]=i;
            for (int j=2*i;j<=n;j+=i) is_prime[j]=false;
        }
    }
    return p;
}
bool ok(ll x)
{
    bool f=0;
    rep(i,K)
    {
        if (x%prime[i]==0)
        {
            f=1;
            x/=prime[i];
            if (x%prime[i]==0)
                return false;
            if (x==1) return true;
        }
    }
    if (!f) return true;
}
int main()
{
    iostream::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    K=sieve(MAXN);
    int o;
    SI(o);
    while(o--)
    {
        ll x;
        SI(x);
        ll sqx=sqrt(x);
        ll mi=LINF,ma=LINF;
        for (int i=sqx+1;i<1e9+9;i++)
        {
            if (ok(i))
            {
                ma=i;
                break;
            }
        }
        for (int i=sqx;i>=2;i--)
        {
            if (ok(i))
            {
                mi=i;
                break;
            }
        }
        PI(min(llabs(ma*ma-x),llabs(mi*mi-x)));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/s1124yy/p/5724941.html