小C的数字倍数问题

210 阅读3分钟

问题理解

我们需要计算在区间 [l, r] 内,有多少个数是 a 的倍数,或者是 b 的倍数,或者是 c 的倍数。

数据结构与算法选择

  1. 直接计数法:我们可以遍历区间 [l, r] 内的每一个数,检查它是否是 ab 或 c 的倍数,如果是则计数加一。这种方法的时间复杂度是 O((r - l) * 3),即 O(n),其中 n 是区间长度。
  2. 数学方法:我们可以利用数学公式来计算。具体来说,我们可以计算区间 [l, r] 内 abc 的倍数的个数,然后使用容斥原理来避免重复计数。这种方法的时间复杂度是 O(1)

算法步骤

  1. 计算单个倍数的个数

    • 计算 a 的倍数的个数:countA = (r / a) - ((l - 1) / a)
    • 计算 b 的倍数的个数:countB = (r / b) - ((l - 1) / b)
    • 计算 c 的倍数的个数:countC = (r / c) - ((l - 1) / c)
  2. 计算两个数的公倍数的个数

    • 计算 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))
  3. 计算三个数的公倍数的个数

    • 计算 ab 和 c 的公倍数的个数:countABC = (r / lcm(a, b, c)) - ((l - 1) / lcm(a, b, c))
  4. 使用容斥原理计算总数

    • 总数 = 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);
    }
    }
    

    关键步骤

  • 计算单个倍数的个数:使用整除运算符 / 计算区间内 abc 的倍数的个数。
  • 计算公倍数的个数:使用 lcm 函数计算两个数或三个数的最小公倍数,然后计算公倍数的个数。
  • 使用容斥原理:通过加减不同组合的倍数个数来避免重复计数。

提示

  • 你可以先实现 gcd 和 lcm 函数,然后再实现 solution 函数。
  • 确保 lcm 函数能够正确处理两个数和三个数的情况。