LeetCode 878. 第 N 個神奇數字

原題地址878. 第 N 個神奇數字


如果正整數可以被 A 或 B 整除,那麼它是神奇的。

返回第 N 個神奇數字。由於答案可能非常大,返回它模 10^9 + 7 的結果

示例 1:
輸入:N = 1, A = 2, B = 3
輸出:2

示例 2:
輸入:N = 4, A = 2, B = 3
輸出:6

示例 3:
輸入:N = 5, A = 2, B = 4
輸出:10

示例 4:
輸入:N = 3, A = 6, B = 4
輸出:8

提示:
1 <= N <= 10^9
2 <= A <= 40000
2 <= B <= 4000

算法

首先找出最大公約數C,如果CAB其中一個數,直接輸出C*N;否則計算出最小公倍數D

 

在一個最小公倍數的週期內即(i*D,(i+1)*D],只有(i+1)*D可以同時整除AB,其餘的數最多僅能整除AB其中一個。

每一個週期內,神奇的數的總數爲D/A+D/B-1

因此把N除以D/A+D/B-1的餘數n單獨拿出來計算即可。

 

保證A<B之後,在一個公倍數週期內,AB可以整除的神奇數分別有a=D/Ab=D/B,且a>b

然後根據b每增加1,對應的a增加多少可以簡化運算,使得結果更快得到第n個數


代碼 

class Solution:
    def nthMagicalNumber(self, N, A, B):
        """
        :type N: int
        :type A: int
        :type B: int
        :rtype: int
        """

        def gcb(p, q):
            if p == q:
                return p
            if p < q:
                return gcb(q, p)
            else:
                if p & 1:
                    if q & 1:
                        return gcb(p - q, q)
                    else:
                        return gcb(p, q >> 1)
                else:
                    if q & 1:
                        return gcb(p >> 1, q)
                    else:
                        return gcb(p >> 1, q >> 1) << 1

        C = gcb(A, B)
        if C == A or C == B:
            return C * N % 1000000007
        if A > B:
            A, B = B, A
        D = A * (B // C)
        a, b = D // A, D // B
        m, n = N // (a + b - 1), N % (a + b - 1)
        y = int(n / (a / b + 1))
        x = int(a / b * y)
        nowA, nowB = A * x, B * y
        while x + y < n:
            if nowA + A < nowB + B:
                nowA += A
                x += 1
            else:
                nowB += B
                y += 1
        return (max(nowA, nowB) + m * D) % 1000000007
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章