歐拉 因式分解法 是一種整數分解 方法,重點是用兩種方式把要分解的數表示為兩數平方和。比如要分解
1000009
{\displaystyle 1000009}
,這個數既能寫成
1000
2
+
3
2
{\displaystyle 1000^{2}+3^{2}}
,又能寫成
972
2
+
235
2
{\displaystyle 972^{2}+235^{2}}
,那麼用歐拉的方法就能分解了:
1000009
=
293
⋅
3413
{\displaystyle 1000009=293\cdot 3413}
。
能用兩種方式把一個整數表示為兩數平方和,或許就能分解這個數,這個想法最早是由梅森 提出的。但是直到一百年後,這個想法才得到了廣泛應用。當時歐拉用他的方法分解了
1000009
{\displaystyle 1000009}
,這個方法也由此得名。當時人們還認為
1000009
{\displaystyle 1000009}
是質數,但是這個數在主流的素性檢測算法中都不是偽質數 。
對於因子相差不是特別小的數,歐拉因式分解法比費馬的方法更高效。如果能比較容易地找出兩種方式把要分解的數表示為兩數平方和,那麼歐拉的方法可能比試除法 高效得多。歐拉取得的進展提高了人們分解整數的效率。20 世紀 10 年代,大因數表已經寫到了將近一千萬[來源請求] 那麼大了。將數字表示為兩數平方和的方法與在費馬因式分解法 中查找平方差的方法基本相同。
歐拉因式分解法最大的缺點是這樣的:要分解的整數,它的質因數分解中,如果有任何一個 4k+3 型的質數是奇數次冪的,那麼歐拉的方法就不能分解了。原因是,這樣的數字不可能是兩數的平方和。4k+1 型的奇合數也經常是兩個 4k+3 型質數的積(例如 3053 = 43 × 71),由上面的結論可以知道,對於這類數,歐拉的方法是用不了的。
這個限制,就讓歐拉因式分解法不太受計算機因子分解算法的歡迎,畢竟對於一個隨機的大數,連能不能用這個方法分解它都很難知道。不過近來,有人嘗試把歐拉的方法發展成計算機算法,用於已知確實可以應用歐拉方法的特定數字。
婆羅摩笈多-斐波那契恆等式 指出,一個兩數平方和,和另一個兩數平方和,它們的乘積,是又一個兩數平方和。歐拉的方法就依賴於這個定理,把它反了過來:給定
n
=
a
2
+
b
2
=
c
2
+
d
2
{\displaystyle n=a^{2}+b^{2}=c^{2}+d^{2}}
,那麼
n
{\displaystyle n}
是兩個(可能不一樣的)兩數平方和的積。
首先移項得到
a
2
−
c
2
=
d
2
−
b
2
{\displaystyle a^{2}-c^{2}=d^{2}-b^{2}}
用平方差公式 ,對兩邊分別因式分解 ,得到
(
a
−
c
)
(
a
+
c
)
=
(
d
−
b
)
(
d
+
b
)
{\displaystyle (a-c)(a+c)=(d-b)(d+b)}
(1)
現在令
k
=
gcd
(
a
−
c
,
d
−
b
)
{\displaystyle k=\operatorname {gcd} (a-c,d-b)}
,令
h
=
gcd
(
a
+
c
,
d
+
b
)
{\displaystyle h=\operatorname {gcd} (a+c,d+b)}
,這樣就有
l
,
m
,
l
′
,
m
′
{\displaystyle l,m,l',m'}
滿足
(
a
−
c
)
=
k
l
{\displaystyle (a-c)=kl}
,
(
d
−
b
)
=
k
m
{\displaystyle (d-b)=km}
,
gcd
(
l
,
m
)
=
1
{\displaystyle \operatorname {gcd} (l,m)=1}
(
a
+
c
)
=
h
m
′
{\displaystyle (a+c)=hm'}
,
(
d
+
b
)
=
h
l
′
{\displaystyle (d+b)=hl'}
,
gcd
(
l
′
,
m
′
)
=
1
{\displaystyle \operatorname {gcd} (l',m')=1}
把這些代入式 (1),得到
k
l
h
m
′
=
k
m
h
l
′
{\displaystyle klhm'=kmhl'}
約去
k
{\displaystyle k}
和
h
{\displaystyle h}
,得到
l
m
′
=
l
′
m
{\displaystyle lm'=l'm}
我們知道
l
,
m
{\displaystyle l,m}
互素,
l
′
,
m
′
{\displaystyle l',m'}
互素,因此
l
=
l
′
{\displaystyle l=l'}
m
=
m
′
{\displaystyle m=m'}
因此
(
a
−
c
)
=
k
l
{\displaystyle (a-c)=kl}
(
d
−
b
)
=
k
m
{\displaystyle (d-b)=km}
(
a
+
c
)
=
h
m
{\displaystyle (a+c)=hm}
(
d
+
b
)
=
h
l
{\displaystyle (d+b)=hl}
可以看到
m
=
gcd
(
a
+
c
,
d
−
b
)
{\displaystyle m=\operatorname {gcd} (a+c,d-b)}
還有
l
=
gcd
(
a
−
c
,
d
+
b
)
{\displaystyle l=\operatorname {gcd} (a-c,d+b)}
現在應用婆羅摩笈多-斐波那契恆等式 ,我們就得到了
(
k
2
+
h
2
)
(
l
2
+
m
2
)
=
(
k
l
+
h
m
)
2
+
(
k
m
−
h
l
)
2
=
(
(
a
−
c
)
+
(
a
+
c
)
)
2
+
(
(
d
−
b
)
−
(
d
+
b
)
)
2
=
(
2
a
)
2
+
(
2
b
)
2
=
4
n
.
{\displaystyle \left(k^{2}+h^{2}\right)\left(l^{2}+m^{2}\right)=(kl+hm)^{2}+(km-hl)^{2}={\bigl (}(a-c)+(a+c){\bigr )}^{2}+{\bigl (}(d-b)-(d+b){\bigr )}^{2}=(2a)^{2}+(2b)^{2}=4n.}
由於每個因子都是兩數平方和,那麼
(
k
,
h
)
{\displaystyle (k,h)}
和
(
l
,
m
)
{\displaystyle (l,m)}
之中必有一個數對中兩個數都是偶數。不失一般性,假設數對
(
k
,
h
)
{\displaystyle (k,h)}
里兩數都是偶數。於是就可以這樣分解了:
n
=
(
(
k
2
)
2
+
(
h
2
)
2
)
(
l
2
+
m
2
)
.
{\displaystyle n=\left(\left({\tfrac {k}{2}}\right)^{2}+\left({\tfrac {h}{2}}\right)^{2}\right)\left(l^{2}+m^{2}\right).\,}
已知
1000009
=
1000
2
+
3
2
=
972
2
+
235
2
{\displaystyle \ 1000009=1000^{2}+3^{2}=972^{2}+235^{2}}
用上面的方法計算:
a = 1000
(A) a − c = 28
k = gcd[A,C] = 4
b = 3
(B) a + c = 1972
h = gcd[B,D] = 34
c = 972
(C) d − b = 232
l = gcd[A,D] = 14
d = 235
(D) d + b = 238
m = gcd[B,C] = 116
於是
1000009
=
[
(
4
2
)
2
+
(
34
2
)
2
]
⋅
[
(
14
2
)
2
+
(
116
2
)
2
]
{\displaystyle 1000009=\left[\left({\frac {4}{2}}\right)^{2}+\left({\frac {34}{2}}\right)^{2}\right]\cdot \left[\left({\frac {14}{2}}\right)^{2}+\left({\frac {116}{2}}\right)^{2}\right]\,}
=
(
2
2
+
17
2
)
⋅
(
7
2
+
58
2
)
{\displaystyle =\left(2^{2}+17^{2}\right)\cdot \left(7^{2}+58^{2}\right)\,}
=
(
4
+
289
)
⋅
(
49
+
3364
)
{\displaystyle =(4+289)\cdot (49+3364)\,}
=
293
⋅
3413
{\displaystyle =293\cdot 3413\,}
function Euler_factorize(int n) -> list[int]
if is_prime(n) then
print("数字是質數,不能分解")
exit function
for-loop from a=1 to a=ceiling(sqrt(n))
b2 = n - a*a
b = floor(sqrt(b2))
if b*b==b2
break loop preserving a,b
if a*a+b*b!=n then
print("数字无法表示成平方和")
exit function
for-loop from c=a+1 to c=ceiling(sqrt(n))
d2 = n - c*c
d = floor(sqrt(d2))
if d*d==d2 then
break loop preserving c,d
if c*c+d*d!=n then
print("没有第二种表示成平方和的方法")
exit function
A = c-a, B = c+a
C = b-d, D = b+d
k = GCD(A,C)//2, h = GCD(B,D)//2
l = GCD(A,D)//2, m = GCD(B,C)//2
factor1 = k*k + h*h
factor2 = l*l + m*m
return list[ factor1, factor2 ]