leetcode 878 第N个神奇的数字

leetcode 878 第N个神奇的数字

此题来源

题目描述

一个正整数如果能被 a 或 b 整除,那么它是神奇的

给定三个整数 n , a , b ,返回第 n 个神奇的数字。因为答案可能很大,所以返回答案 对 109 + 7 取模 后的值。

样例表示

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

输出:2

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

输出:6

数据范围

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

算法分析

  • 思路1

使用是想的暴力去判断每个数是否符合神奇的数字,然后进行计数,得到最后的答案

因为数据量是4e13暴力回超时

class Solution {
    public int nthMagicalNumber(int n, int a, int b) {
        int nums = 1;
        while(n > 0){
            if(check(nums,a,b)){
                nums++;
                n--;
            }else{
                nums++;
            }
        }
        return (nums - 1)%(1e9+7) ;
    }
    boolean check(int n , int a,int b){
        boolean aa = false;
        boolean bb = false;
        if(n%a == 0){
            aa = true;
        }
        if(n%b == 0){
            bb = true;
        }
        return aa || bb;
    }
}
  • 思路2

因为神奇的数是被a或者b 进行整除,那我们可以将答案划分在下面的集合视图中

image-20221127213857166

注意 lcm 是求最小公倍数 gcd 是求最大公倍数

 int gcd(int a, int b){
 	return b == 0? a: gcd(b,a%b);
 }
 lcm = a * b/ gcd(a,b)
 

因为我们要求的答案是在1-N中 满足N/a + N/b - N / lcm (a,b) >= n的最小值

同时N和n 是满足单调递增的,所以可以使用二分答案的方法来快速的计算我们需要的最小值N

java代码

class Solution {
    //容斥原理
    //x 满足x/a + x/b -x/(lcm(a,b)) >= n
    public int nthMagicalNumber(int n, int a, int b) {  
        long l = (long)1;
        long r = (long)1e14;
        while(l<r){
        long mid = l+r >> 1;
        if(mid/a + mid/b - mid/(a*b/gcd(a,b)) >= n){
            r = mid;    
        }else{
            l = mid+1;
        }    
    }
        return (int)(l % (1e9+7));
    }
    int gcd(int a, int b){
        return b!=0? gcd(b,a%b):a;
    } 
}

python 代码

注意: python 中对数字的向下取整方法

class Solution:

    def nthMagicalNumber(self, n: int, a: int, b: int) -> int:
        l = 1
        r = 1e14
        while l < r:
            mid = int((l+r)//2)
            count = int(mid//a) + int(mid//b) - int(mid//(math.lcm(a,b)));
            if count >= n:
                r = mid
            else:
                l = mid + 1
        return int(r % (1e9+7))

c++ 代码

class Solution {
    const int  mod = 1e9+7;
public:
    int nthMagicalNumber(int n, int a, int b) {
        long long l = 1;
        long long r = 1e14;
        while(l<r){
            long long mid = l+r >> 1;
            if(mid/a + mid/b - mid/(a*b/gcd(a,b)) >= n){
                r = mid;
            }else{
                l = mid + 1;
            }
        }
        return (int)(r % mod);
    }
    int gcd(int a,int b){
        return b == 0?  a : gcd(b, a%b);
    }
};

d + 1;
}
}
return (int)(r % mod);
}
int gcd(int a,int b){
return b == 0? a : gcd(b, a%b);
}
};


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值