フェルマー法による素因数分解+Pythonでの実装

投稿日: 更新日:

フェルマー法とは

NNが奇数の時、整数a,ba,bを用いてN=a2b2N=a^2-b^2変形できる性質を利用します。 そうすると、N=(a+b)(ab)N=(a+b)(a-b)の積の形に分解でき因数は(a+b)(a+b)(ab)(a-b)であることが分かります!
NNが偶数の場合は2で割り続ければよいです!
この手法はN\sqrt{N}の付近から探索していくため平方数に近い数の場合に有効な手法です。

複数の素数からなる数の場合

先ほど説明した通りフェルマー法は1つの数を2つの数に分解するだけでした。そんな方法で素因数分解できるのでしょうか?

ちゃんとできます!!

N=17×47×59×97N = 17 \times 47 \times 59 \times 97の場合は以下のように分解されて素因数分解できます。

フェルマー法での素因数分解の流れ

計算方法

前提条件としてNNは正の整数かつ奇数、a,ba, bは0以上の整数です。
まず、N=a2b2N = a^2 - b^2を式変形します。

N=a2b2 よりb2=a2N\begin{aligned} N &= a^2 - b^2 より\\ b^2 &= a^2 - N \end{aligned}

したがって、

b=a2Nb = \sqrt{a^2 - N}

となりaaの値が求まればbbの値が求まる状態になりました。
ルートの中身は0以上でなければならないので、aaの値の範囲はaNa \geqq \sqrt{N}であることも分かります。
後はaNa \geqq \sqrt{N}を満たす整数aaを下から順番に試してa2N\sqrt{a^2 - N}が整数となったところが答えです!

練習問題

161をフェルマー法を用いて素因数分解してください。

解答

1. a2161a^2 \geqq 161を満たす最小のaaを求める

122=144, 132=16912^2 = 144,\ 13^2 = 169より、a=13a = 13と求まりました!

2. bbが整数になるまで試す!

a=13a=13の時、b=169161=8b = \sqrt{169-161} = \sqrt{8} より、整数でない。
a=14a=14の時、b=196161=35b = \sqrt{196-161} = \sqrt{35} より、整数でない。
a=15a=15の時、b=225161=64=8b = \sqrt{225-161} = \sqrt{64} = 8 より、整数となる!
以上よりb=8b = 8となりました!

3. (a+b),(ab)(a+b),(a-b)を求める

a=15,b=8a = 15, b=8ですので、
(a+b)=23,(ab)=7(a+b) = 23, (a-b) = 7となる。 したがって、161=23×7161 = 23 \times 7 となり素因巣分解できました。

今回求めた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

N=a2b2N = a^2 - 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での実装は使う場面もあると思いますのでぜひ活用してください。

書いた人

profile_image

お茶の葉

物理とプログラミングが好きな人