• 【leetcode】1201. Ugly Number III


    题目如下:

    Write a program to find the n-th ugly number.

    Ugly numbers are positive integers which are divisible by a or b or c.

    Example 1:

    Input: n = 3, a = 2, b = 3, c = 5
    Output: 4
    Explanation: The ugly numbers are 2, 3, 4, 5, 6, 8, 9, 10... The 3rd is 4.

    Example 2:

    Input: n = 4, a = 2, b = 3, c = 4
    Output: 6
    Explanation: The ugly numbers are 2, 3, 4, 6, 8, 9, 10, 12... The 4th is 6.
    

    Example 3:

    Input: n = 5, a = 2, b = 11, c = 13
    Output: 10
    Explanation: The ugly numbers are 2, 4, 6, 8, 10, 11, 12, 13... The 5th is 10.
    

    Example 4:

    Input: n = 1000000000, a = 2, b = 217983653, c = 336916467
    Output: 1999999984
    

    Constraints:

    • 1 <= n, a, b, c <= 10^9
    • 1 <= a * b * c <= 10^18
    • It's guaranteed that the result will be in range [1, 2 * 10^9]

    解题思路:先看这么一个问题,怎么求出任意一个数x,在[1,x]区间内有几个丑数?只要(x/a)+(x/b)+(x/c)即可,但是可能会有重复的值,比如a=2,b=3时,丑数6就会多计算一次,所以还需要减去( x/lcm(a,b) + x/lcm(c,b)  + x/lcm(a,c) )。这里lcm(a,b)表示a和b的最小公倍数。这样是不是就好了呢?还有lcm(a,b,c)的情况,因为前面求两两最小公倍数的时候多减了一次,所以这里要再加上 x/lcm(a,b,c) ,这里就可以得到x前面有几个丑数,即为count。由于x不一定是丑数,所有只要求出小于x的最大丑数,这个丑数所在的位置就是count。由于丑数的数量随着x的增加而增加,所以用二分查找的方法很容易就可以求得指定位置的丑数。

    代码如下:

    class Solution(object):
        def nthUglyNumber(self, n, a, b, c):
            """
            :type n: int
            :type a: int
            :type b: int
            :type c: int
            :rtype: int
            """
            def gcd(a, b):
                return a if b == 0 else gcd(b, a % b)
            def lcm(a, b):
                return a * b // gcd(a, b)
            def getCount(v,divisor):
                return v / divisor
            divisor_list = sorted([a,b,c])
            if divisor_list[2] % divisor_list[0] == 0:
                del divisor_list[2]
            if divisor_list[1] % divisor_list[0] == 0:
                del divisor_list[1]
            if len(divisor_list) == 3 and divisor_list[2] % divisor_list[1] == 0:
                del divisor_list[2]
    
            lcm_list = set()
            for i in range(len(divisor_list)):
                for j in range(len(divisor_list)):
                    if i != j:lcm_list.add(lcm(divisor_list[i],divisor_list[j]))
            common_lcm = None
            if len(divisor_list) == 3:
                common_lcm = lcm(divisor_list[0],divisor_list[1])
                common_lcm = lcm(common_lcm, divisor_list[2])
    
            low ,high = 1, 2*(10**9)
            val = 0
            while low <= high:
                #print low,high
                mid = (low + high)/2
                #mid = 120
                #if mid == 128:
                #    pass
                ugly_count = 0
                for i in divisor_list:
                    ugly_count += getCount(mid,i)
                for i in lcm_list:
                    ugly_count -= getCount(mid,i)
                if common_lcm != None:
                    ugly_count += getCount(mid,common_lcm)
                if n == ugly_count:
                    val = mid
                    break
                elif n > ugly_count:
                    low = mid + 1
                else:
                    high = mid - 1
            res = []
            for i in divisor_list:
                res.append(val/i*i)
            for i in lcm_list:
                res.append(val / i * i)
            return sorted(res)[-1]
  • 相关阅读:
    hdu5945 Fxx and game
    hdu5937 Equation
    2016-2017 CT S03E06: Codeforces Trainings Season 3 Episode 6 The Baguette Master
    Canada Cup 2016 D. Contest Balloons
    hdu5798 Stabilization
    bzoj 4026 dC Loves Number Theory
    Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) C. Ray Tracing
    hdu5923 Prediction
    hdu5925 Coconuts
    2016弱校联盟十一专场10.2 Longest Increasing Subsequence
  • 原文地址:https://www.cnblogs.com/seyjs/p/11582940.html
Copyright © 2020-2023  润新知