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 modulo 109 + 7
.
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 <= 109
2 <= a, b <= 4 * 104
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
We need to find the nth number that is divisible by either one number (let's call it A) or another number (let's call it B). The brute force way is just to start counting up from one and check each number one by one.
Here's how the algorithm would work step-by-step:
def find_nth_magical_number_brute_force(n, first_divisor, second_divisor):
current_number = 0
magical_number_count = 0
while True:
current_number += 1
# Check if the current number is divisible by either divisor.
if (current_number % first_divisor == 0) or (current_number % second_divisor == 0):
magical_number_count += 1
# If we've found the nth magical number, return it.
if magical_number_count == n:
return current_number
This problem is about finding the nth number that is divisible by either of two given numbers. We will use a clever strategy based on binary search to efficiently find the answer without checking every number. This dramatically speeds up the process.
Here's how the algorithm would work step-by-step:
def nth_magical_number(n, a, b):
modulo = 10**9 + 7
least_common_multiple = (a * b) // gcd(a, b)
low = min(a, b)
high = n * min(a, b)
while low < high:
middle = (low + high) // 2
# Calculate the number of magical numbers less than or equal to middle.
count = (middle // a) + (middle // b) - (middle // least_common_multiple)
# Adjust search range based on the count.
if count < n:
low = middle + 1
else:
high = middle
# Ensure result is within constraints.
return low % modulo
def gcd(a, b):
#Euclidean Algorithm
while b:
a, b = b, a % b
return a
Case | How to Handle |
---|---|
n is zero | Return 0, as there is no 0th magical number by definition. |
a or b is zero | If either a or b is zero, all multiples of the other will be magical numbers, so return n * (the non-zero number). |
n is very large (approaching maximum integer value) | Use binary search with 64 bit integers to avoid overflow in calculations of high and mid values. |
a and b are equal | All multiples of a (or b) will be magical numbers, so return n * a. |
a or b is 1 | The first n natural numbers are magical so return n. |
LCM(a, b) is very large (close to the max integer value) | Pre-calculate LCM(a, b) using 64 bit integers to avoid overflow during binary search calculations and take mod before returning the answer. |
a and b are prime numbers | The number of magical numbers up to 'mid' is mid/a + mid/b - mid/(a*b), which simplifies the calculation in the binary search. |
Integer overflow when calculating mid/a, mid/b or mid/lcm during the binary search. | Use 64-bit integers for mid, a, b, and lcm to prevent integer overflows when performing the divisions. |