kAri OJ130 非平方等式(二分加枚举)
2016-03-14 14:30
288 查看
130. 非平方等式
时间限制 1000 ms 内存限制 262144KB
题目描述
考虑等式: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; }
相关文章推荐
- iOS 利用runtime关联对象
- Integrity Measurement Architecture
- [疯狂Java]AWT剪切板:图像传递
- Spring ContextLoaderListener与DispatcherServlet所加载的applicationContext的区别
- Android 开发随谈
- 【翻译】bc400课程中的Authorization Check 授权检查
- SAP 工厂日生产计划待排维护
- rsync的常用命令,及实现远程备份
- inception_mysql运维自动化管理
- 别傻了,人家离职你也离
- LEETCODE 191
- 弹性scrollview的实现
- 1-git branch的使用
- MySql中inner join和left join的特殊情况
- java获得磁盘、网络实时I/O速率
- Mybatis概述
- iOS 基础知识大全(OC篇零基础可学习)
- cron 定时任务
- linux 运行class文件
- 【Junit】The import org.junit.Test conflicts with a type defined in the same file报错