Leetcode.878 第 N 个神奇数字

题目链接

Leetcode.878 第 N 个神奇数字 Rating : 1898

题目描述

一个正整数如果能被 ab 整除,那么它是神奇的。

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

示例 1:

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

示例 2:

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

提示:

  • 1 < = n < = 1 0 9 1 <= n <= 10^9 1<=n<=109
  • 2 < = a , b < = 4 ∗ 1 0 4 2 <= a, b <= 4 * 10^4 2<=a,b<=4104

解法:二分 + 容斥原理

对于 k k k 个数( 1 − k 1 - k 1k),我们做出如下定义:

  • 定义 A A A 为能被 a a a 整除的数,即 k / a k/a k/a
  • 定义 B B B 为能被 b b b 整除的数,即 k / b k/b k/b
  • 定义 C C C 为既能被 a a a 整除的数 ,也能被 b b b 整除的数,即 k / l c m ( a , b ) k/lcm(a,b) k/lcm(a,b)

所以能被 a a a 或者 b b b 整除的数为: t o t a l = A + B − C total = A+B-C total=A+BC

我们通过 二分 的方式,求第一个 t o t a l ≥ n total \geq n totaln 的数即可。

二分的左区间 l = 2 l = 2 l=2;二分的右区间为 r = n ∗ m i n { a , b } r = n * min\{ a , b \} r=nmin{a,b}

时间复杂度: O ( l o g n ) O(logn) O(logn)

C++代码:

const int MOD = 1e9+7;
using LL = long long;

class Solution {
public:
    int nthMagicalNumber(int n, int a, int b) {
        LL lc = lcm<LL>(a,b);

        LL l = 2 , r = n * 1LL * min(a,b);
        while(l < r){
            LL mid = (l + r) >> 1;
            LL total = mid / a + mid / b - mid / lc;
            if(total >= n) r = mid;
            else l = mid + 1;
        }

        return (int)(l % MOD);
    }
};

你可能感兴趣的:(Leetcode,leetcode,容斥原理,二分)