解方程

Description

Jre最近在学习数学,他遇到了如下的问题: 
对于方程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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值