878. 第 N 个神奇数字

题目

一个正整数如果能被 a 或 b 整除,那么它是神奇的。
给定三个整数 n , a , b ,返回第 n 个神奇的数字。因为答案可能很大,所以返回答案 对 109 + 7 取模 后的值。

示例

  • 示例 1:

输入:n = 1, a = 2, b = 3
输出:2

  • 示例 2:

输入:n = 4, a = 2, b = 3
输出:6

提示

1 <= n <= 109
2 <= a, b <= 4 * 104

代码

package Algorithm.LeetCode.nthMagicalNumber;

/**
 * @author yangyiliy_liuyang
 * 2022/11/22
 * @version 1.0
 * 878. 第 N 个神奇数字
 */
public class Main {
    public static void main(String[] args) {
        int i = nthMagicalNumber(4, 2, 3);
        System.out.println(i);
    }

    /**
     * 求一个数字m 在【1,m】中有多少个数可以被a或者b整除
     * 容斥原理
     * m/a+m/b - m/lca(a,b)           //lca最小公倍数
     * lca(a,b) = a*b/gcd(a,b)        //gcd最大公约数(大公因数)
     * gcd(a,b) =
     * if b == 0:
     * return a
     * else
     * return gcd(b, a%b)
     *
     * @param n
     * @param a
     * @param b
     * @return
     */
    private static final long MOD = (long) 1e9 + 7;

    public static int nthMagicalNumber(int n, int a, int b) {
        long lca = a / gcd(a, b) * b;
        long left = 1, right = (long) Math.max(a, b) * n;
        while (left < right) {
            long mid = left + (right - left) / 2;
            if (mid / a + mid / b - mid / lca >= n) {
                right = mid; 
                // 范围缩小到 (left, mid)
            } else {
                left = mid + 1; 
                // 范围缩小到 (mid, right)
            }
        }
        return (int) (right % MOD);
    }

    private static int gcd(int a, int b) {
        return b == 0 ? a : gcd(b, a % b);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值