您的位置:首页 > 其它

kAri OJ130 非平方等式(二分加枚举)

2016-03-14 14:30 288 查看


130. 非平方等式

时间限制 1000 ms 内存限制 262144
KB


题目描述

考虑等式:
x2 + s(x)·x - n = 0, 
其中x,n是正整数,s(x)是个函数,其值等于x在十进制下所有数字的和。
现给出整数n的大小,请你求出最小的满足条件的正整数x。


输入格式

输入仅包含一个整数n (1 ≤ n ≤ 1018) .


输出格式

如果不存在这样的x,请输出-1;否则请输出满足条件的最小的整数x (x > 0)


输入样例

2


输出样例

1

解题思路:

1)如果采取从1到sqrt(n)枚举的话,复杂度是O(10^9),肯定会超时。

2)容易想到把范围缩小再枚举,于是尝试从sqrt(n)-1000000到sqrt(n)枚举,不过WA掉了。

于是开始想到更换思路。

x*x+S(x)*x随着x是近似单调递增的。可以试着二分。

不过,把1-1000的x*x+S(x)*x函数值打印出来。会发现不是严格单调递增。



可以先根据二分确定大致范围,然后这个范围内枚举。

(直接枚举会超时,直接二分会WA掉。)

PS:由于n最大是10^18,所以要用long long.

AC代码:
#include<iostream>
#include<cmath>
using namespace std;

long long getval(long long tmp)
{
long long ans=0;
long long t=tmp;
while(tmp)
{
ans+=tmp%10;
tmp/=10;
}

ans=ans*t+t*t;
return ans;
}

int main()
{

/*for(long long i=1;i<=1000;i++)
{
cout<<getval(i)<<" ";
if(i%10==0) cout<<endl;
}*/

long long n;
while(cin>>n)
{
long long l=1;
long long r=sqrt(n);
long long mid;

int flag=0;
while(l<=r)
{
mid=(l+r)/2;
if(getval(mid)==n)
{
break;
}
if(getval(mid)<n)
l=mid+1;
else
r=mid-1;
}

long long mi=mid-100000;
if(mi<1) mi=1;
long long ma=mid+100000;
if(ma>sqrt(n))  ma=sqrt(n);
for(long long i=mi; i<=ma; i++)
{
if(getval(i)==n)
{
flag=1;
cout<<i<<endl;
break;
}
}

if(!flag)
cout<<"-1"<<endl;
}
return 0;
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: