LeetCode 1201. Ugly Number III 数学+二分答案

发布时间 2023-07-19 21:04:36作者: Blackzxy

An ugly number is a positive integer that is divisible by \(a\), \(b\), or \(c\).

Given four integers \(n\), \(a\), \(b\), and \(c\), return the \(n\)th ugly number.

Solution

考虑如何二分答案,假设一个函数 \(f(num,a,b,c)\) 会得到 \([1,num]\) 中 ugly number的个数,所以就是搜索左侧边界的二分

那么个数该如何求解呢?\([1,num]\) 中能被 \(a\) 整除的数个数为 \(num/a\), 同时被 \(a,b\) 整除的个数为 \(num/lcm(a,b)\),那么根据容斥即可

点击查看代码
class Solution:
    def nthUglyNumber(self, n: int, a: int, b: int, c: int) -> int:
        def gcd(a, b):
            if a<b:
                return gcd(b,a)
            if b==0:
                return a
            return gcd(b, a%b)
        
        def lcm(a, b):
            return a*b/gcd(a,b)
        
        def check(cand, a, b, c):
            setA, setB, setC = int(cand/a), int(cand/b), int(cand/c)
            setAB, setAC, setBC = int(cand/lcm(a,b)), int(cand/lcm(a,c)), int(cand/lcm(b,c))
            setABC = int(cand/lcm(lcm(a,b),c))
            return setA+setB+setC-setAB-setAC-setBC+setABC
        
        left = 1
        right = int(2e9)+1

        while left<=right:
            mid = left+int((right-left)/2)
            if check(mid, a, b , c) < n:
                left=mid+1
            else:
                right=mid-1
        return left