桁数が多い場合、GCD を見つけるためのユークリッド アルゴリズム ( https://en.wikipedia.org/wiki/Euclidean_algorithm#Algorithmic_efficiency ) の効率的な実装が、私が考えることができる最良のルートです。素因数分解には高速で一般的なアルゴリズムがないため、それを使用して問題を軽減しても実行時間は短縮されません。これに役立つ迅速な削減については知りません。
大きなNに対処すると、これは他の人が得ているものだと思います:
- 配列をソートする
- 最小値から開始し、短絡を使用して LCM を計算します (たとえば、GCD 部分にユークリッド アルゴリズムを使用)。残りのペアの LCM がこれまでに見つかった最良の値より小さくならない場合は、処理を停止します。ソート済みセット内の 2 つの数値 b < c の場合、LCM の下限は (b * c) / b = c であることに注意してください (これは、b が c を除算するときに発生します)。以下の作業コードを参照してください (short_lcm バージョン)。
これに対して行うことができる他の最適化があります (python で記述しないなど:) ) が、これはアルゴリズムの改善を示しています。
import fractions
def lcm(a, b):
return abs(a * b) / fractions.gcd(a, b)
def short_lcm(a):
a = sorted(a)
iterations = 0
cur_lcm = lcm(a[0], a[1])
first = a[0]
second = a[1]
for i in range(0, len(a)):
#Best case for remaining pairs
if i < len(a) - 1 and a[i + 1] >= cur_lcm: break
for j in range(i + 1, len(a)): #Starting at i + 1 avoids duplicates
if a[j] >= cur_lcm: break #Best case for remaining pairs
iterations += 1
test = lcm(a[i], a[j])
if test < cur_lcm:
cur_lcm = test
first = a[i]
second = a[j]
if iterations < 1: iterations = 1
print("Lowest LCM pair is (%d, %d): %d. Found in %d iterations" % (
first, second, cur_lcm, iterations))
def long_lcm(a):
iterations = 0
cur_lcm = lcm(a[0], a[1])
first = a[0]
second = a[1]
for i in range(0, len(a)):
for j in range(i + 1, len(a)): #Starting at i + 1 avoids duplicates
iterations += 1
test = lcm(a[i], a[j])
if test < cur_lcm:
cur_lcm = test
first = a[i]
second = a[j]
print("Lowest LCM pair is (%d, %d): %d. Found in %d iterations" % (
first, second, cur_lcm, iterations))
if __name__ == '__main__':
from random import randint
import time
a = [randint(1, 1000) for r in xrange(100)]
#Only print the list if it's relatively short
if len(a) < 20: print a
#Try all pairs
start = time.clock()
long_lcm(a)
print "Slow version time: %f\n" % (time.clock() - start)
start = time.clock()
short_lcm(a)
print "Fast version time: %f" % (time.clock() - start)