{x}
blog image

Nth Magical Number

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

Solution Explanation for Nth Magical Number

This problem asks to find the nth number that is divisible by either a or b. A straightforward approach would be to iteratively generate numbers and check divisibility, but this is inefficient for large n. A more efficient solution utilizes binary search and the inclusion-exclusion principle.

Core Idea:

The number of magical numbers less than or equal to x can be calculated using the inclusion-exclusion principle:

count(x) = floor(x/a) + floor(x/b) - floor(x/lcm(a,b))

  • floor(x/a): counts numbers divisible by a.
  • floor(x/b): counts numbers divisible by b.
  • floor(x/lcm(a,b)): corrects for double-counting numbers divisible by both a and b (i.e., divisible by their least common multiple).

We want to find the smallest x such that count(x) = n. This is done efficiently using binary search.

Algorithm:

  1. Find LCM: Calculate the least common multiple (lcm) of a and b. The gcd (greatest common divisor) function is used as a helper to compute the LCM efficiently using the formula: lcm(a, b) = (a * b) / gcd(a, b).

  2. Binary Search: Perform a binary search within a suitable range. The upper bound of the search range can be estimated as (a + b) * n, as it is unlikely for the nth magical number to exceed this. The lower bound is 0.

  3. Count Magical Numbers: In each iteration of the binary search, calculate count(mid) using the inclusion-exclusion formula, where mid is the midpoint of the current search range.

  4. Adjust Search Range: If count(mid) is greater than or equal to n, it means the nth magical number is less than or equal to mid, so we narrow down the search range to the lower half. Otherwise, we search in the upper half.

  5. Return Result: The binary search converges to the smallest x such that count(x) >= n, which is the nth magical number. We then return this value modulo 10^9 + 7.

Time Complexity Analysis:

  • gcd function: O(log(min(a, b))) due to the recursive nature.
  • Binary Search: O(log((a+b)*n)). The search space is proportional to (a+b)*n.
  • count calculation: O(1) for each iteration.

Therefore, the overall time complexity is dominated by the binary search, resulting in O(log((a+b)*n)).

Space Complexity Analysis:

The space complexity is O(1) as we only use a constant number of variables to store intermediate values.

Code Explanation (Python):

import math
 
def gcd(a, b):
    while b:
        a, b = b, a % b
    return a
 
def lcm(a, b):
    return a * b // gcd(a, b)
 
class Solution:
    def nthMagicalNumber(self, n: int, a: int, b: int) -> int:
        mod = 10**9 + 7
        l, r = 0, (a+b)*n  # Search range
        c = lcm(a,b)
 
        while l<=r:
            mid = (l+r)//2
            count = mid//a + mid//b - mid//c
            if count >=n:
                r = mid -1
            else:
                l = mid + 1
        return (l)%mod
 

The other languages (Java, C++, Go) follow the same logic but have different syntax. The key components remain consistent: the gcd, lcm, binary search, and the inclusion-exclusion principle for counting magical numbers.