hdu 5778 abs (数论)

10 篇文章 0 订阅


abs

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 491    Accepted Submission(s): 176


Problem Description

Given a number x, ask positive integer y2 , 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.

 


Input

The first line of input is an integer T ( 1T50 )
For each test case,the single line contains, an integer x ( 1x1018 )

 


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

 


Source

BestCoder Round #85


解题思路:解决本题的关键是怎么处理一个数的所有质因子都只出现两次,所以我采用的做法先对这个数开根号(原来数的范围太大),直接对这个新的数进行质因数分解O(sqrt(n)),然后判断所有因数的乘积是否等于它本身。剩下就是对给定的数开根号然后暴力的上下枚举啦~ (^_^)

这道题其实应用了一个隐含的素数定理:任意相邻的两个素数之间的距离接近lg(n),也就保证了本题的时间复杂度一定可行~

心得:当时比赛的时候写了40分钟,结果一直WA,比完后才突然意识到题目说y>=2.....T^T  给一组数据(iput:1 1 )(output:3),好多人都是输出0的...

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <utility>
using namespace std;

#define inf 0x3f3f3f3f
typedef long long ll;

bool factor(ll n)//这里对一个整数进行质因数分解
{
    ll m = 1;
    ll num = n;
    set<int>ret;
    int sqrtn = int(sqrt(n));
    for(int div = 2; div <= sqrtn; div++)
    {
        while(n%div==0)
        {
            n /= div;
            ret.insert(div);
        }
    }
    if(n>1) ret.insert(n);
    set<int>::iterator it;
    for(it=ret.begin();it!=ret.end();it++)
        m *= (*it);
    if(m==num)    return true;//判断所有质因数的乘积是否等于其本身
    return false;
}
int main()
{
    //freopen("test.txt","w",stdout);
    int t;
    cin>>t;
    ll x;
    while(t--)
    {
        cin>>x;
        ll temp = int(sqrt(x));
        ll a,b;
        ll ans;
        ll ans1 = 1e18;//初始化为一个比较大的数即可,应该不用这么大
        ll ans2 = 1e18;
        a = temp + 1;
        b = temp;
        while(1)//向上查找
        {
            if(a+1>=1000000000)
                break;
            if(factor(a))
            {
                ans1 = abs(a*a-x);
                break;
            }

            a++;
        }
        while(1)//向下查找
        {
            if(b<2)//注意判断这个结束条件,y>=2
                break;
            if(factor(b))
            {
                ans2 = abs(b*b-x);
                break;
            }
            
            b--;
        }
        ans = min(ans1,ans2);
        cout << ans << endl;
    }

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值