Description
Jre最近在学习数学,他遇到了如下的问题:
对于方程x*x + s(x)*x - n = 0,n为正整数S(x)表示十进制数x的各个位上的数字之和。现在给定n,请帮Jre求解方程的最小的正整数根x,否则确定没有满足的正整数根。
对于方程x*x + s(x)*x - n = 0,n为正整数S(x)表示十进制数x的各个位上的数字之和。现在给定n,请帮Jre求解方程的最小的正整数根x,否则确定没有满足的正整数根。
Input
多组输入,每组输入一个正整数n(1<=n<=1,000,000,000,000,000,000),输入以文件尾(EOF)结束。
Output
组输出,如果没有最小正整数根输出-1,否则输出方程的最小正整数根。每组输出独占一行。
Sample Input
2
110
10
Sample Output
1
10
-1
HINT
样例一:x = 1 为最小正根,因为 s(1) = 1 , 1*1 + 1*1 - 2 = 0。
样例二:x = 10为最小正根,因为 s(10) = 1 + 0 = 1, 10*10 + 1*10 - 110 = 0。
样例三:没有满足的正根。
思路:①x*x + s(x)*x - n = 0将方程①转换为②
② s(x)*x - n = n - x*x 由②可知:x的最大范围即为sqrt(n),因为n-sqrt(n)*sqrt(n) = 0, 所以x的范围为1~sqrt(n),
范围找到了,直接用二分法查找即可。
但是,查找的时候不能用原式查找,因为s(x)不是固定值,它会随着x的值大小波动
此时再从方程出发找条件,n-x*x 这个就可以判断!
if(n - x*x > x) 范围缩到大值
if(n - x*x < x) 范围缩到小值
if(x*x + s(x) * x == n) 成立,即为找到!
代码:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int decompose(long long n)//分解数求和,求s(x)的值
{
int sum = 0;
while(n)
{
sum += n%10;
n /= 10;
}
return sum;}
int findTwo(int l,int r,long long n)//二分查找
{
int head = l,tail = r,mid,x;
while(head <= tail)
{
mid = (head + tail) / 2;
x = mid;
if(x*x + decompose(x) * x == n) return x;//满足
if(n - x*x > x)
head = mid + 1;
if(n - x*x < x)
tail = mid - 1;
}
return -1;}
int main()
{
long long n;
while(scanf("%lld",&n)!=EOF)
{
printf("%d\n",findTwo(1,sqrt(n),n));
}
return 0;
}