フェルマー法による素因数分解+Pythonでの実装
投稿日: 更新日:
フェルマー法とは
が奇数の時、整数を用いて変形できる性質を利用します。
そうすると、の積の形に分解でき因数はとであることが分かります!
が偶数の場合は2で割り続ければよいです!
この手法はの付近から探索していくため平方数に近い数の場合に有効な手法です。
複数の素数からなる数の場合
先ほど説明した通りフェルマー法は1つの数を2つの数に分解するだけでした。そんな方法で素因数分解できるのでしょうか?
ちゃんとできます!!
の場合は以下のように分解されて素因数分解できます。
計算方法
前提条件としては正の整数かつ奇数、は0以上の整数です。
まず、を式変形します。
したがって、
となりの値が求まればの値が求まる状態になりました。
ルートの中身は0以上でなければならないので、の値の範囲はであることも分かります。
後はを満たす整数を下から順番に試してが整数となったところが答えです!
練習問題
161をフェルマー法を用いて素因数分解してください。
解答
1. を満たす最小のを求める
より、と求まりました!
2. が整数になるまで試す!
の時、 より、整数でない。
の時、 より、整数でない。
の時、 より、整数となる!
以上よりとなりました!
3. を求める
ですので、
となる。
したがって、 となり素因巣分解できました。
今回求めた161は13の平方数に近い値なので3回の総当たりで求めることができました。平方数から遠い場合はどうなるか気になる人は159で計算してみてください。
Pythonでの実装
それではPythonで実装します!2パターンあります。
入力のNはどちらも奇数であることが前提です。
パターン1
練習問題の解法と同じような手法で解いてくパターンです。平方数の判定にgmpy2を利用します。
from math import isqrt
import gmpy2
def fermat(N):
a = 1 + isqrt(N - 1) # N <= a^2 を満たす最大のaを求める
while not gmpy2.is_square(a*a - N):
a += 1
b = isqrt(a*a - N)
return a+b, a-b
パターン2
となるようにa, bを増やすやり方です。gmpyを必要としません。
from math import isqrt
def fermat(N):
a = 1 + isqrt(N - 1) # N <= a^2 を満たす最大のaを求める
b = isqrt(a*a - N)
while True:
w = a*a - b*b - N
if w == 0:
return a+b, a-b
elif w > 0:
b += 1
elif w < 0:
a += 1
まとめ
フェルマー法による素因数分解についてまとめました!Pythonでの実装は使う場面もあると思いますのでぜひ活用してください。