设a,b是任意两个正整数。记r-2 = a,r-1 = b,反复运用带余除法,有
r-2 = q0r-1 + r0 , 0 ≤ r0 < r-1
r-1 = q1r0 + r1 , 0 ≤ r1 < r0
r0 = q2r1 + r2 , 0 ≤ r2 < r1
…
rn-3 = qn-1rn-2 + rn-1 , 0 ≤ rn-1 < rn-2
rn-2 = qnrn-1 + rn , 0 ≤ rn < rn-1
rn-1 = qn+1rn + rn+1 , rn+1 = 0
随着n的增加,rn减小,由于rn+1 ≥ 0,因此,rn+1 = 0。
上述过程即从数列r-2,r-1,r0,…,rn前两项依次求出第三项,直到最后一项的过程。有(a,b)=(r-2,r-1)=(r-1,r0)= … =(rn-1,rn)=(rn,rn+1)=(rn,0)=rn。
如果将这一过程反方向写出,有
rn = rn-2 – qnrn-1
rn-1 = rn-3 – qn-1rn-2
…
r2 = r0 – q2r1
r1 = r-1 – q1r0
r0 = r-2 – q0r-1
即rn,rn-1,…,r1,r0中每一项均可以用后两项表示。于是rn可以用r-2,r-1表示,即可以找到整数s,t,使得
设a,b是任意两个正整数,则
s n a + t n b = ( a , b ) (式 1.3 ) s_na + t_nb = (a,b)(式1.3) sna+tnb=(a,b)(式1.3)
对于j = 0,1,…,n-1,这里sj,tj归纳定义为
s − 2 = 1 , s − 1 = 0 , s j = s j − 2 − q j s j − 1 s_{-2} =1,s_{-1}=0,s_j=s_{j-2}-q_js_{j-1} s−2=1,s−1=0,sj=sj−2−qjsj−1
t − 2 = 0 , t − 1 = 1 , t j = t j − 2 − q j t j − 1 (式 1.4 ) t_{-2}=0,t_{-1}=1,t_j=t_{j-2} -q_jt_{j-1}(式1.4) t−2=0,t−1=1,tj=tj−2−qjtj−1(式1.4)
其中j = 0,1,2,…,n-1,n。qi = [rj-2 / rj-1]是上式的不完全商。设x∈R,[x]表示不超过x的最大整数,称为实数x的整数部分。
证明:
只需证明:对于j = -2,-1,0,1,…,n-1
s j a + t j b = r j ( 式 1.5 ) s_ja+t_jb =r_j(式1.5) sja+tjb=rj(式1.5)
其中rj = rj-2 - qjrj-1是(式1.5)中的余数。因为(a,b)= rn,所以
s n a + t n b = ( a , b ) s_na+t_nb=(a,b) sna+tnb=(a,b)
对j用数学归纳法来证明式(1.5)。当j = -2时,有s-2 = 1,t-2 = 0以及
s − 2 a + t − 2 b = a = r − 2 s_{-2}a+t_{-2}b=a=r_{-2} s−2a+t−2b=a=r−2
式(1.5)对于j = -2成立。
j = -1时,有s-1 = 0,t-1 = 1,以及
s − 1 a + t − 1 b = b = r − 1 s_{-1}a+t_{-1}b=b=r_{-1} s−1a+t−1b=b=r−1
式(1.5)对于j = -1成立。
假设式(1.5)对于-2 ≤ j ≤ k-1成立,即
s j a + t j b = r j s_ja+t_jb=r_j sja+tjb=rj
对于j = k,有
r k = r k − 2 − q k r k − 1 r_k=r_{k-2} - q_kr_{k-1} rk=rk−2−qkrk−1
利用归纳假设,得到
r k = ( s k − 2 a + t k − 2 b ) − q k ( s k − 1 a + t k − 1 b ) r_k =(s_{k-2}a+t_{k-2}b)-q_k(s_{k-1}a+t_{k-1}b) rk=(sk−2a+tk−2b)−qk(sk−1a+tk−1b)
r k = ( s k − 2 − q k s k − 1 ) a + ( t k − 2 − q k t k − 1 ) b r_k=(s_{k-2}-q_ks_{k-1})a+(t_{k-2}-q_kt_{k-1})b rk=(sk−2−qksk−1)a+(tk−2−qktk−1)b
r k = s k a + t k b r_k=s_ka+t_kb rk=ska+tkb
因此,式(1.5)对于j = k成立。
根据数学归纳法,式(1.5)对所有的j = -2,-1,0,1,…,n-1成立。
下面根据上面的证明设计一个算法:假设a和b是不全为零的非负整数,计算s,t使得sa + tb =(a,b)。
首先,令
r − 2 = a r − 1 = b r_{-2}=a\qquad r_{-1}=b r−2=ar−1=b
s − 2 = 1 s − 1 = 0 s_{-2}=1\qquad s_{-1} = 0 s−2=1s−1=0
t − 2 = 0 t − 1 = 1 t_{-2}=0\qquad t_{-1}=1 t−2=0t−1=1
这是因为rk = ska + tkb,所以r-2 = s-2a + t-2b = 1✖a + 0✖b = a,r-1 = s-1a + t-1b = 0✖a + 1✖b = b。
(1)如果r-1 = 0,则令
s = s − 2 t = t − 2 s = s_{-2}\qquad t = t_{-2} s=s−2t=t−2
否则,计算
q 0 = [ r − 2 / r − 1 ] r 0 = r − 2 − q 0 r − 1 q_0=[r_{-2}/r_{-1}]\qquad r_0=r_{-2}-q_0r_{-1} q0=[r−2/r−1]r0=r−2−q0r−1
(2)如果r0 = 0,则令
s = s − 1 t = t − 1 s=s_{-1}\qquad t = t_{-1} s=s−1t=t−1
否则,计算
s 0 = s − 2 − q 0 s − 1 t 0 = t − 2 − q 0 t − 1 s_0=s_{-2}-q_0s_{-1}\qquad t_0=t_{-2}-q_0t_{-1} s0=s−2−q0s−1t0=t−2−q0t−1
以及
q 1 = [ r − 1 / r 0 ] r 1 = r − 1 − q 1 r 0 q_1=[r_{-1}/r_0]\qquad r_1=r_{-1}-q_1r_0 q1=[r−1/r0]r1=r−1−q1r0
(3)如果r1 = 0,则令
s = s 0 t = t 0 s = s_0\qquad t = t_0 s=s0t=t0
否则,计算
s 1 = s − 1 − q 1 s 0 t 1 = t − 1 − q 1 t 0 s_1=s_{-1}-q_1s_0\qquad t_1=t_{-1}-q_1t_0 s1=s−1−q1s0t1=t−1−q1t0
以及
q 2 = [ r 0 / r 1 ] r 2 = r 0 − q 2 r 1 q_2 = [r_0/r_1]\qquad r_2 = r_0 - q_2r_1 q2=[r0/r1]r2=r0−q2r1
. . . ... ...
(j+1)如果rj-1 = 0(j ≥ 3),则令
s = s j − 2 t = t j − 2 s = s_{j-2}\qquad t = t_{j-2} s=sj−2t=tj−2
否则,计算
s j − 1 = s j − 3 − q j − 1 s j − 2 s_{j-1}=s_{j-3}-q_{j-1}s_{j-2} sj−1=sj−3−qj−1sj−2
t j − 1 = t j − 3 − q j − 1 t j − 2 t_{j-1}=t_{j-3}-q_{j-1}t_{j-2} tj−1=tj−3−qj−1tj−2
以及
q j = [ r j − 2 / r j − 1 ] r j = r j − 2 − q j r j − 1 q_j=[r_{j-2}/r_{j-1}]\quad r_j=r_{j-2}-q_jr_{j-1} qj=[rj−2/rj−1]rj=rj−2−qjrj−1
最后,一定有rn+1 = 0。这时,令
s = s n t = t n s=s_n\qquad t=t_n s=snt=tn
总之,可以找到整数s,t,使得
s a + t b = r n = ( a , b ) sa+tb=r_n=(a,b) sa+tb=rn=(a,b)
将上述算法可写成以下python代码:
from euclid import *
def func(a, b):
r = [a, b]
q = [0, 0]
s = [1, 0]
t = [0, 1]
i = 2
if r[1] == 0:
return s[0], t[0]
else:
next_q = r[0] // r[1]
next_r = r[0] - next_q * r[1]
r.append(next_r)
q.append(next_q)
while r[i] != 0:
next_s = s[i-2] - q[i] * s[i-1]
next_t = t[i-2] - q[i] * t[i-1]
next_q = r[i-1] // r[i]
next_r = r[i-1] - next_q * r[i]
r.append(next_r)
q.append(next_q)
s.append(next_s)
t.append(next_t)
i += 1
return s[i-1], t[i-1]
print(func(202, 282))
print('202 *', func(202, 282)[0], ' + 282 *', func(202, 282)[1], '=', gcdIter(202, 282))
print(func(1613, 3589))
print('1613 *', func(1613, 3589)[0], ' + 3589 *', func(1613, 3589)[1], '=', gcdIter(1613, 3589))
print(func(1859, 1573))
print('1859 *', func(1859, 1573)[0], ' + 1573 *', func(1859, 1573)[1], '=', gcdIter(1859, 1573))
其中eculid模块是自己编写的用来求解最大公约数,详情可以参考信息安全数学基础——欧几里得算法
本文主要介绍了扩展欧几里得算法,其在求解乘法逆元时会非常有帮助。