数字覆盖问题,没什么解题思想,如果说有的话,就是数学观察,代码如下
package com.wly.algorithmproblem; /** * 数字覆盖问题 * 题目详情 给定整数区间[a,b]和整数区间[x,y],你可以使用任意多次a,b之间的整数做加法,可以凑出多少个[x,y]区间内的整数? 输入 a,b,x,y,其中1<= a < b <= 1000000000, 1 <= x < y <= 1000000000。 输出: 用[a,b]内的整数做任意多次加法,可以得到多少个[x,y]内的整数。 例如a = 8, b = 10, x = 3 , y = 20 我们可以得到 [3..20]之间的整数 8, 9, 10, 16 ( 8 + 8), 17(8 + 9), 18(9 + 9), 19(9 + 10), 20(10 + 10),因此输出8。 问:2+3=5 1+4=5 这算1个还是2个? 答:算1次 问你能覆盖多少个不同的数字 [x,y]全覆盖住得话 就是y - x + 1。 * @author wly * */ public class howmany { public static void main(String[] args) { long time1; // int max = 10000; int max = 1000000000; time1 = System.currentTimeMillis(); System.out.println("m1:" + howmany(3,4,10,max)); //999999440,5242 System.out.println(System.currentTimeMillis() - time1); time1 = System.currentTimeMillis(); // System.out.println("m2:" + howmany2(400000000,400000050,1,1000000000)); //33993551 System.out.println("m2:" + howmany2(3,4,10,max)); //33993551 System.out.println(System.currentTimeMillis() - time1); } public static int howmany(int a,int b,int x,int y) { int num = 0; long times = 0; if(x < a) { x = a; } for(int i=x;i<=y;i++) { times = i /a; if(times*b >= i) { num ++; // System.out.print(i + " "); } else { continue ; } } return num; } /** * 结题思想: * 本解法基本没有使用算法思想,主要是从数学推理解得的,根据题目要求若x可用[m,n]表示,则x属于[c*m,c*(m+n)],其中c是>=1的正整数 * 或者说[c*m,c*(m+n)]中的元素总是可以用[m,n]中的元素来表示 * 公式推理过程:设一个[c*m,c*(m+n)]中的数c*m + an + b,则c*m + an + b = a(m+n) + (c-a)m * b,其中1<=b<=n * @param a * @param b * @param x * @param y * @return */ public static int howmany2(int a,int b,int x,int y) { int num = 0; long times = 0; if(a >= b || x >= y) { return 0; } if(x < a) { x = a; } //优化解法 int i = x; //-------就因为这里出错了,哎,,, while(i <= y) { //使用while来实现i的改变 times = i /a; if(times*b > i) { int delta; if(times*b >= y) { delta = (int) (y - i+1); } else { delta = (int) (times*b - i+1); } num = (int)(num + delta); i = delta + i; // System.out.print(i + " "); } else if(times*b == i) { i ++; num ++; } else { //无解情况 i ++; } } return num; } }
运行结果:
m1:999999991 3430 m2:999999991 0
O啦~~~