We need to find the nth number divisible by either a or b. Direct simulation is too slow for large n. Instead, we use binary search and inclusion-exclusion to count how many numbers ≤ x are divisible by a or b.
Let L = lcm(a, b). For any x, the count of magical numbers ≤ x is (x // a) + (x // b) - (x // L). Use binary search to find the smallest x such that this count ≥ n. Return x modulo 1e9+7.
intnthMagicalNumber(int n, int a, int b) {
long mod =1e9+7;
long l = min(a, b), r = (long)n * min(a, b);
long L = lcm(a, b);
while (l < r) {
long m = l + (r-l)/2;
if (m/a + m/b - m/L < n) l = m+1;
else r = m;
}
return l % mod;
}
funcgcd(a, bint) int {
forb!=0 {
a, b = b, a%b }
returna}
funcnthMagicalNumber(n, a, bint) int {
mod:= int(1e9+7)
l, r:= min(a, b), n*min(a, b)
L:=a*b/gcd(a, b)
forl < r {
m:=l+ (r-l)/2ifm/a+m/b-m/L < n {
l = m+1 } else {
r = m }
}
returnl%mod}
func min(a, bint) int { ifa < b { returna } else { returnb } }
publicintnthMagicalNumber(int n, int a, int b) {
long mod = 1_000_000_007L;
long l = Math.min(a, b), r = (long)n * Math.min(a, b);
long L = lcm(a, b);
while (l < r) {
long m = l + (r-l)/2;
if (m/a + m/b - m/L < n) l = m+1;
else r = m;
}
return (int)(l % mod);
}
privatelonglcm(int a, int b) {
return (long)a * b / gcd(a, b);
}
privateintgcd(int a, int b) {
while (b != 0) {
int t = b; b = a % b; a = t;
}
return a;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
funnthMagicalNumber(n: Int, a: Int, b: Int): Int {
val mod = 1_000_000_007L
var l = minOf(a, b).toLong()
var r = n.toLong() * minOf(a, b)
val L = lcm(a, b)
while (l < r) {
val m = l + (r-l)/2if (m/a + m/b - m/L < n) l = m+1else r = m
}
return (l % mod).toInt()
}
funlcm(a: Int, b: Int): Long = a.toLong() * b / gcd(a, b)
fungcd(a: Int, b: Int): Int = if (b ==0) a else gcd(b, a % b)
1
2
3
4
5
6
7
8
9
10
11
12
defnthMagicalNumber(n: int, a: int, b: int) -> int:
import math
mod =10**9+7 l, r = min(a, b), n * min(a, b)
L = a * b // math.gcd(a, b)
while l < r:
m = (l + r) //2if m//a + m//b - m//L < n:
l = m +1else:
r = m
return l % mod
impl Solution {
pubfnnth_magical_number(n: i32, a: i32, b: i32) -> i32 {
fngcd(mut a: i64, mut b: i64) -> i64 {
while b !=0 {
let t = b; b = a % b; a = t;
}
a
}
let mod_ =1_000_000_007;
let (a, b, n) = (a asi64, b asi64, n asi64);
let l = a.min(b);
letmut left = l;
letmut right = n * l;
let lcm = a * b / gcd(a, b);
while left < right {
let m = left + (right - left) /2;
if m/a + m/b - m/lcm < n {
left = m +1;
} else {
right = m;
}
}
(left % mod_) asi32 }
}