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
原创文章 26 获赞 20 访问量 3万+

猜你喜欢

转载自blog.csdn.net/HJXINKKL/article/details/83342811