Ugly Number III

medium binary search inclusion-exclusion math

Problem

An ugly number is a positive integer divisible by a, b, or c. Given four integers n, a, b, and c, return the nth ugly number.

Inputn = 4, a = 2, b = 3, c = 5
Output5
The sequence of ugly numbers is 2, 3, 4, 5, 6, 8, ... The 4th one is 5.

from math import gcd

def nth_ugly_number(n, a, b, c):
    ab = a * b // gcd(a, b)
    ac = a * c // gcd(a, c)
    bc = b * c // gcd(b, c)
    abc = ab * c // gcd(ab, c)

    def count(x):
        return (x // a + x // b + x // c
                - x // ab - x // ac - x // bc
                + x // abc)

    lo, hi = 1, 2 * 10**9
    while lo < hi:
        mid = (lo + hi) // 2
        if count(mid) < n:
            lo = mid + 1
        else:
            hi = mid
    return lo
function nthUglyNumber(n, a, b, c) {
  const gcd = (x, y) => y === 0 ? x : gcd(y, x % y);
  const lcm = (x, y) => x / gcd(x, y) * y;
  const ab = lcm(a, b), ac = lcm(a, c), bc = lcm(b, c);
  const abc = lcm(ab, c);
  const count = (x) =>
    Math.floor(x / a) + Math.floor(x / b) + Math.floor(x / c)
    - Math.floor(x / ab) - Math.floor(x / ac) - Math.floor(x / bc)
    + Math.floor(x / abc);

  let lo = 1, hi = 2e9;
  while (lo < hi) {
    const mid = Math.floor((lo + hi) / 2);
    if (count(mid) < n) lo = mid + 1;
    else hi = mid;
  }
  return lo;
}
class Solution {
    public int nthUglyNumber(int n, int a, int b, int c) {
        long ab = lcm(a, b), ac = lcm(a, c), bc = lcm(b, c);
        long abc = lcm(ab, c);
        long lo = 1, hi = 2_000_000_000L;
        while (lo < hi) {
            long mid = (lo + hi) / 2;
            long cnt = mid/a + mid/b + mid/c
                     - mid/ab - mid/ac - mid/bc + mid/abc;
            if (cnt < n) lo = mid + 1;
            else hi = mid;
        }
        return (int) lo;
    }
    private long lcm(long x, long y) { return x / gcd(x, y) * y; }
    private long gcd(long x, long y) { return y == 0 ? x : gcd(y, x % y); }
}
class Solution {
public:
    int nthUglyNumber(int n, int a, int b, int c) {
        long ab = lcm((long)a, b), ac = lcm((long)a, c), bc = lcm((long)b, c);
        long abc = lcm(ab, (long)c);
        long lo = 1, hi = 2000000000L;
        while (lo < hi) {
            long mid = (lo + hi) / 2;
            long cnt = mid/a + mid/b + mid/c
                     - mid/ab - mid/ac - mid/bc + mid/abc;
            if (cnt < n) lo = mid + 1;
            else hi = mid;
        }
        return (int) lo;
    }
private:
    long lcm(long x, long y) { return x / __gcd(x, y) * y; }
};
Time: O(log(n·max(a,b,c))) Space: O(1)