原題地址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,如果C爲A或B其中一個數,直接輸出C*N;否則計算出最小公倍數D。
在一個最小公倍數的週期內即(i*D,(i+1)*D],只有(i+1)*D可以同時整除A和B,其餘的數最多僅能整除A或B其中一個。
每一個週期內,神奇的數的總數爲D/A+D/B-1
因此把N除以D/A+D/B-1的餘數n單獨拿出來計算即可。
保證A<B之後,在一個公倍數週期內,A、B可以整除的神奇數分別有a=D/A、b=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