题解
题目难度:简单
知识点:数学问题,二分算法
分析:
针对本题,有两种方法,一种利用数学思想,较为直接粗暴的搜索;另一种方法可以利用二分法来解决
方法1:
针对本题,第一想法是通过暴力的方法利用数学思路解答,给出sum的值求原值x(如果存在则为x,否则x=-1),那么sum = x+(1/10)x+(1/100)x+…。以例子sum= 564为例计算,x≈508,与真实结果509相差很少,可以通过从508开始往后展开n个元素的搜索,这样也可以在一定程度上减少搜索范围。因为sum的范围在[1, 10^18],所以要适当扩大搜索范围,在这个数据范围中n取100。
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); long sum = sc.nextLong(); // 1. 暴力数学搜索法 System.out.println(mathSolve(sum)); } private static long mathSolve(long sum) { // 统计位数 int count = 0; long tmp = sum; while(tmp>0){ count++; tmp/=10; } //统计除数 double chu = 0; for(int i=0;i<count;i++){ chu += 1 / Math.pow(10, i); // 1+0.1+0.01+... } //获取第一个搜索数 long begin = (long) (sum/chu); //开始搜索 long res = search(sum,begin); return res; } private static long search(long sum, long begin) { for(long i = begin; i<begin+100;i++){ long tmp = i; long sum2 = 0; while (tmp > 0) { sum2 += tmp; tmp /= 10; } if (sum2 - sum ==0) { return i ; } } return -1; } }
方法2:
利用二分思想解决问题:设置左右两个指针left和right,sum值一定大于要求的真实值,所以这两个指针可以分别指向1和输入的sum,找到中间mid值,求mid值对应的总和’sum’进行比较。
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); long sum = sc.nextLong(); // 2. 利用二分查找的方法 System.out.println(BineraySearchSolve(sum)); } private static long BineraySearchSolve(long sum) { long tmp = sum; long left = 0 ; long right = sum; while(left<=right){ long mid = (left+right)/2; // 二分找到mid,求其sum值,与输入的sum值比较是否相等。 long theSum = getSum(mid); if(theSum == sum){ return mid; }else if(theSum > sum){ right = mid - 1; }else{ left = mid + 1; } } return -1; } private static long getSum(long mid) { long res = 0; while(mid>0){ res+=mid; mid/=10; } return res; } }