问题理解
我们需要计算在区间 [l, r] 内,有多少个数是 a 的倍数,或者是 b 的倍数,或者是 c 的倍数。
数据结构与算法选择
- 直接计数法:我们可以遍历区间
[l, r]内的每一个数,检查它是否是a、b或c的倍数,如果是则计数加一。这种方法的时间复杂度是O((r - l) * 3),即O(n),其中n是区间长度。 - 数学方法:我们可以利用数学公式来计算。具体来说,我们可以计算区间
[l, r]内a、b、c的倍数的个数,然后使用容斥原理来避免重复计数。这种方法的时间复杂度是O(1)。
算法步骤
-
计算单个倍数的个数:
- 计算
a的倍数的个数:countA = (r / a) - ((l - 1) / a) - 计算
b的倍数的个数:countB = (r / b) - ((l - 1) / b) - 计算
c的倍数的个数:countC = (r / c) - ((l - 1) / c)
- 计算
-
计算两个数的公倍数的个数:
- 计算
a和b的公倍数的个数:countAB = (r / lcm(a, b)) - ((l - 1) / lcm(a, b)) - 计算
a和c的公倍数的个数:countAC = (r / lcm(a, c)) - ((l - 1) / lcm(a, c)) - 计算
b和c的公倍数的个数:countBC = (r / lcm(b, c)) - ((l - 1) / lcm(b, c))
- 计算
-
计算三个数的公倍数的个数:
- 计算
a、b和c的公倍数的个数:countABC = (r / lcm(a, b, c)) - ((l - 1) / lcm(a, b, c))
- 计算
-
使用容斥原理计算总数:
- 总数 =
countA + countB + countC - countAB - countAC - countBC + countABC
代码框架
public class Main { public static int solution(int a, int b, int c, int l, int r) { // 计算单个倍数的个数 int countA = (r / a) - ((l - 1) / a); int countB = (r / b) - ((l - 1) / b); int countC = (r / c) - ((l - 1) / c);
// 计算两个数的公倍数的个数 int countAB = (r / lcm(a, b)) - ((l - 1) / lcm(a, b)); int countAC = (r / lcm(a, c)) - ((l - 1) / lcm(a, c)); int countBC = (r / lcm(b, c)) - ((l - 1) / lcm(b, c)); // 计算三个数的公倍数的个数 int countABC = (r / lcm(a, b, c)) - ((l - 1) / lcm(a, b, c)); // 使用容斥原理计算总数 int totalCount = countA + countB + countC - countAB - countAC - countBC + countABC; return totalCount; } // 计算两个数的最小公倍数 private static int lcm(int a, int b) { return a * (b / gcd(a, b)); } // 计算三个数的最小公倍数 private static int lcm(int a, int b, int c) { return lcm(lcm(a, b), c); } // 计算两个数的最大公约数 private static int gcd(int a, int b) { while (b != 0) { int temp = b; b = a % b; a = temp; } return a; } public static void main(String[] args) { System.out.println(solution(2, 3, 4, 1, 10) == 7); System.out.println(solution(5, 7, 11, 15, 100) == 34); System.out.println(solution(1, 1, 1, 1, 1000) == 1000); } }关键步骤
- 总数 =
- 计算单个倍数的个数:使用整除运算符
/计算区间内a、b、c的倍数的个数。 - 计算公倍数的个数:使用
lcm函数计算两个数或三个数的最小公倍数,然后计算公倍数的个数。 - 使用容斥原理:通过加减不同组合的倍数个数来避免重复计数。
提示
- 你可以先实现
gcd和lcm函数,然后再实现solution函数。 - 确保
lcm函数能够正确处理两个数和三个数的情况。