編集:これは今正しいはずだと思います。
このアルゴリズムは、因数分解に依存せず、ユークリッド アルゴリズムとその変形にのみ依存します。これにより、因数分解を使用するソリューションよりも数学的に洗練されたものになりますが、はるかに高速になります。ユークリッド アルゴリズムと対数を理解していれば、数学は問題にならないはずです。
(1) 数字のセットをソートします。の形式の番号がありますab^{n1} < .. < ab^{nk}
。
例:(3 * 2, 3*2^5, 3*2^7, 3*2^13)
(2) ソート済みリストの (n+1) 番目の要素の n 番目の要素を (n) 番目の要素で割った新しいリストを作成します。あなたは今持っていb^{n2 - n1}, b^{n3 - n2}, ..., b^{nk - n(k-1)}
ます。
(続き) 例:(2^4, 2^2, 2^6)
定義します (これをプログラムしないでください -- プログラムがどのように動作するかを説明するためだけに、プログラムが不明であるd_i = n_(i+1) - n_i
ため、プログラムしたくてもできませんでした)。n_i
(続き) 例:d_1 = 4, d_2 = 2, d_3 = 6
(a = 3, b = 2)
この例の問題では、またはを自由に選択できることに注意してください(a = 3/2, b = 4)
。要点は、ステップ (2) からリスト内のすべてのエントリを分割する「実数」の任意の累乗がb
正解です。したがってb
、すべてを割る任意の累乗d_i
(この場合は 4、2、および 6 を割る任意の累乗) に累乗できるということになります。問題は、私たちがどちらb
も知らないことd_i
です。しかし、 を にすれば、m = gcd(d_1, ... d_(k-1))
を見つけることができますb^m
。これで十分です。
注: と が与えられるb^i
と、以下を使用してb^j
見つけることができます。b^gcd(i, j)
log(b^i) / log(b^j) = (i log b) / (j log b) = i/j
これにより、ユークリッド アルゴリズムの修正版を使用して を見つけることができますb^gcd(i, j)
。「アクション」はすべて指数にあります。加算は乗算に、乗算はべき乗に、(結果として)商は対数に置き換えられました。
import math
def power_remainder(a, b):
q = int(math.log(a) / math.log(b))
return a / (b ** q)
def power_gcd(a, b):
while b != 1:
a, b = b, power_remainder(a, b)
return a
(3) 元の集合のすべての要素は のべき乗だけ異なるためr = b^gcd(d_1, ..., d_(k-1))
、それらはすべて、cr^n
必要に応じて の形式です。ただし、c
整数ではない場合があります。問題がある場合はお知らせください。