2 回答

TA貢獻1802條經驗 獲得超5個贊
如果您唯一擔心的是內存不足,您可以使用生成器。
def coprimes(n):
? ? for i in range(1,n):
? ? ? ? if gcd(i, n) == 1:
? ? ? ? ? ? yield i
這樣您就可以使用互質值,然后在不需要時將其丟棄。然而,沒有什么可以改變你的代碼是 O(N^2) 并且對于大素數總是執行緩慢的事實。這假設歐幾里得算法是恒定時間的,但事實并非如此。

TA貢獻1852條經驗 獲得超1個贊
您可以改變策略并從共同素因數的角度來解決這個問題。n 和 m 之間的公共互質將是不能被任何公共質因數整除的所有數字。
def primeFactors(N):
p = 2
while p*p<=N:
count = 0
while N%p == 0:
count += 1
N //= p
if count: yield p
p += 1 + (p&1)
if N>1: yield N
import math
def compare2(n,m):
# skip list for multiples of common prime factors
skip = { p:p for p in primeFactors(math.gcd(n,m)) }
for x in range(1,min(m,n)):
if x in skip:
p = skip[x] # skip multiple of common prime
m = x + p # determine next multiple to skip
while m in skip: m += p # for that prime
skip[m] = p
else:
yield x # comon coprime of n and m
性能比匹配互質列表要好得多,尤其是在較大的數字上:
from timeit import timeit
timeit(lambda:list(compare2(10**5,2*10**5)),number=1)
# 0.025 second
timeit(lambda:list(compare2(10**6,2*10**6)),number=1)
# 0.196 second
timeit(lambda:list(compare2(10**7,2*10**7)),number=1)
# 2.18 seconds
timeit(lambda:list(compare2(10**8,2*10**8)),number=1)
# 20.3 seconds
timeit(lambda:list(compare2(10**9,2*10**9)),number=1)
# 504 seconds
在某些時候,構建所有互質列表會成為瓶頸,您應該在它們從生成器中出來時使用/處理它們(例如計算有多少個):
timeit(lambda:sum(1 for _ in compare2(10**9,2*10**9)),number=1)
# 341 seconds
解決這個問題的另一種方法是列出 n 和 m 之間的 gcd 的互質數,該方法比質因數方法慢一些,但編碼更簡單:
import math
def compare3(n,m):
d = math.gcd(n,m)
for c in range(1,min(n,m)):
if math.gcd(c,d) == 1:
yield c
timeit(lambda:list(compare3(10**6,2*10**6)),number=1)
# 0.28 second
timeit(lambda:list(compare3(10**7,2*10**7)),number=1)
# 2.84 seconds
timeit(lambda:list(compare3(10**8,2*10**8)),number=1)
# 30.8 seconds
鑒于它不使用內存資源,因此在某些情況下可能是有利的:
timeit(lambda:sum(1 for _ in compare3(10**9,2*10**9)),number=1)
# 326 seconds
添加回答
舉報