Nth Magical Number
HardUpdated: Aug 2, 2025
Practice on:
Problem
A positive integer is magical if it is divisible by either a or b.
Given the three integers n, a, and b, return the nth magical number.
Since the answer may be very large, return it modulo10^9 + 7.
Examples
Example 1
Input: n = 1, a = 2, b = 3
Output: 2
Example 2
Input: n = 4, a = 2, b = 3
Output: 6
Constraints
1 <= n <= 10^92 <= a, b <= 4 * 10^4
Solution
Method 1 -
Intuition
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.
Approach
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.
Code
C++
int nthMagicalNumber(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;
}
Go
func gcd(a, b int) int {
for b != 0 {
a, b = b, a%b
}
return a
}
func nthMagicalNumber(n, a, b int) int {
mod := int(1e9+7)
l, r := min(a, b), n*min(a, b)
L := a * b / gcd(a, b)
for l < r {
m := l + (r-l)/2
if m/a + m/b - m/L < n {
l = m + 1
} else {
r = m
}
}
return l % mod
}
func min(a, b int) int { if a < b { return a } else { return b } }
Java
public int nthMagicalNumber(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);
}
private long lcm(int a, int b) {
return (long)a * b / gcd(a, b);
}
private int gcd(int a, int b) {
while (b != 0) {
int t = b; b = a % b; a = t;
}
return a;
}
Kotlin
fun nthMagicalNumber(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)/2
if (m/a + m/b - m/L < n) l = m+1
else r = m
}
return (l % mod).toInt()
}
fun lcm(a: Int, b: Int): Long = a.toLong() * b / gcd(a, b)
fun gcd(a: Int, b: Int): Int = if (b == 0) a else gcd(b, a % b)
Python
def nthMagicalNumber(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) // 2
if m//a + m//b - m//L < n:
l = m + 1
else:
r = m
return l % mod
Rust
impl Solution {
pub fn nth_magical_number(n: i32, a: i32, b: i32) -> i32 {
fn gcd(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 as i64, b as i64, n as i64);
let l = a.min(b);
let mut left = l;
let mut 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_) as i32
}
}
TypeScript
function gcd(a: number, b: number): number {
while (b !== 0) {
[a, b] = [b, a % b];
}
return a;
}
function nthMagicalNumber(n: number, a: number, b: number): number {
const mod = 1e9 + 7;
let l = Math.min(a, b), r = n * Math.min(a, b);
const L = a * b / gcd(a, b);
while (l < r) {
const m = Math.floor((l + r) / 2);
if (Math.floor(m/a) + Math.floor(m/b) - Math.floor(m/L) < n) l = m + 1;
else r = m;
}
return l % mod;
}
Complexity
- ⏰ Time complexity:
O(log(n * min(a, b)))due to binary search. - 🧺 Space complexity:
O(1).