You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将统计1~d中被k/l/m/n整除数的算法时间复杂度降至O(1)

O(1)时间复杂度实现方案

核心原理

使用容斥原理计算1~d范围内能被任意目标数整除的数字总个数,无需遍历1到d的所有数字,运算次数固定,时间复杂度为常数级O(1)。
四个集合的容斥计算公式如下:

符合条件的总数量 = 单个数字的倍数总数 - 任意两个数字公倍数的倍数总数 + 任意三个数字公倍数的倍数总数 - 四个数字公倍数的倍数总数
其中每个类别的数量直接用d / 对应最小公倍数即可得到(Java整数除法默认向下取整,刚好符合需求)。

依赖基础工具方法

需要先实现两个基础运算:

  • 最大公约数(GCD):采用欧几里得算法快速计算
  • 最小公倍数(LCM):LCM(a,b) = a * b / GCD(a,b),注意先做除法再做乘法,避免整数溢出

完整代码实现

import java.util.Scanner;

public class CountDivisible {
    // 计算最大公约数
    private static int gcd(int a, int b) {
        return b == 0 ? a : gcd(b, a % b);
    }

    // 计算最小公倍数
    private static int lcm(int a, int b) {
        if (a == 0 || b == 0) return 0;
        return a / gcd(a, b) * b;
    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int k = in.nextInt();
        int l = in.nextInt();
        int m = in.nextInt();
        int n = in.nextInt();
        int d = in.nextInt();

        // 单个数的倍数总数
        long s1 = (long) d / k + d / l + d / m + d / n;
        // 任意两个数公倍数的倍数总数
        long s2 = (long) d / lcm(k, l) + d / lcm(k, m) + d / lcm(k, n)
                + d / lcm(l, m) + d / lcm(l, n) + d / lcm(m, n);
        // 任意三个数公倍数的倍数总数
        long s3 = (long) d / lcm(lcm(k, l), m) + d / lcm(lcm(k, l), n)
                + d / lcm(lcm(k, m), n) + d / lcm(lcm(l, m), n);
        // 四个数公倍数的倍数总数
        long s4 = (long) d / lcm(lcm(lcm(k, l), m), n);

        long sum = s1 - s2 + s3 - s4;
        System.out.println(sum);
    }
}

方案优势

  • 完全不需要循环遍历,运算次数和d的大小完全无关,即便d取1e9甚至更大的数值也能瞬间得到结果
  • 结果和遍历方案完全一致,容斥原理天然解决了重复统计的问题

内容的提问来源于stack exchange,提问作者TTiM3R

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 23:54:03