北邮OJ 非平方等式

思路是好思路,题是好题,但是数据真的有点差劲... ...有点弱

首先第一眼,我还以为是1e8,上来long long暴力,955ms过了... ...

之后我就懵了,这啥题啊

后来一看,哦,1e18,的确按理不能暴力

那不暴力吧,简单分析一下,x²+s(x)*x=n,左右随意夹一下,不就是2*x²=n和x²=n吗,

那不就是sqrt(n/2)<=x<=sqrt(n)嘛,上来直接写

#include<iostream>
#include<cstdio>
#include<queue>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<sstream>
#include<map>
using namespace std;
long long deal(long long num){
    long long ans=0;
    while(num){
        ans+=num%10;
        num/=10;
    }
    return ans;
}
int main(){
    std::ios::sync_with_stdio(false);
    long long n;
    while(cin>>n){
        bool judge=false;
        for(long long i=sqrt(n/2);i<=sqrt(n);i++){
            if(i*i+deal(i)*i==n){
                judge=true;
                cout<<i<<endl;
                break;
            }
        }
        if(judge==false)
            cout<<"-1"<<endl;
    }
}

随意交一发,又过了... ...

作为一名ACM集训队成员,按理来说这么随意的分析是不能过的啊... ...

不过耗时400多ms,而刚刚在我之前有个2ms过的大佬

这可不行,继续优化

我们从一开始分析

x²+s(x)*x=n,如果左侧去掉s(x)*x,则肯定左侧变小了是不是

也就是x²<=n 

也就是x<=sqrt(n)     【式子1】

另外s(x)最大是9*18=162(因为最大1e18,假设每一位都是9)

那么就有x²+162x>=n   【式子2】

我们看看这个n能不能凑出x,从而整个式子消去x,否则式子很难化简

根据式子1,我们左右各乘以sqrt(n),这样就会出来n了是不

也就是变为成了x*sqrt(n)<=n 【式子3】

将式子3代入到式子2中,也就是x²+162x>=x*sqrt(n)

消去x,也就是x+162>=sqrt(n)

也就是x>=sqrt(n)-162 【式子4】

结合式子1和式子4,写代码即可

最终运行3ms,哦豁,完事,收工

代码要注意sqrt(n)-162可能会复数,所以要写一个max函数,从正整数开始

#include<iostream>
#include<cstdio>
#include<queue>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<sstream>
#include<map>
using namespace std;
long long deal(long long num){
    long long ans=0;
    while(num){
        ans+=num%10;
        num/=10;
    }
    return ans;
}
long long max(long long a,long long b){
    if(a>b)
        return a;
    else
        return b;
}
int main(){
    std::ios::sync_with_stdio(false);
    long long n;
    while(cin>>n){
        bool judge=false;
        for(long long i=max((sqrt(n)-162),1);i<=sqrt(n);i++){
            if(i*i+deal(i)*i==n){
                judge=true;
                cout<<i<<endl;
                break;
            }
        }
        if(judge==false)
            cout<<"-1"<<endl;
    }
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值