题目
一个正整数如果能被 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);
}
}