上一篇:欧几里得算法
概念:
对于不全为0的非负整数
a
,
b
a,b
a,b,
gcd
(
a
,
b
)
\gcd(a, b)
gcd(a,b) 表示
a
,
b
a,b
a,b 的最大公约数,必然存在整数对
x
,
y
x,y
x,y ,使得
g
c
d
(
a
,
b
)
=
a
x
+
b
y
gcd(a,b) = ax + by
gcd(a,b)=ax+by 。
给定
a
a
a 和
b
b
b ,拓展欧几里得算法可以计算出这个整数对
x
,
y
x,y
x,y 。
证明&&基本算法:
(以下证明过程中所有的 / / / 均为整除)
设 a > b a > b a>b 。
-
b
=
0
b=0
b=0
则 gcd ( a , b ) = a \gcd(a,b)=a gcd(a,b)=a 。此时 x = 1 , y = 0 x=1,y=0 x=1,y=0 。 -
b
≠
0
b≠0
b̸=0
∵ a > b > 0 \because a>b>0 ∵a>b>0
∴ a ≠ 0 \therefore a\ne 0 ∴a̸=0
设 a x 1 + b y 1 = gcd ( a , b ) ax1+\qquad b\qquad y1=\gcd(a,b) ax1+by1=gcd(a,b)
b x 2 + ( a   m o d   b ) y 2 = gcd ( b , a   m o d   b ) \quad bx2+\ (a\bmod b)\ y2=\gcd(b,a\bmod b) bx2+ (amodb) y2=gcd(b,amodb)
∵ gcd ( a , b ) = gcd ( b , a   m o d   b ) ∵\gcd(a,b) = \gcd(b,a\bmod b) ∵gcd(a,b)=gcd(b,amodb)(欧几里得原理)
∴ a x 1 + b y 1 = b x 2 + ( a   m o d   b ) y 2 ∴ax1+by1 = bx2+(a\bmod b)y2 ∴ax1+by1=bx2+(amodb)y2
​ 即 a x 1 + b y 1 = b x 2 + ( a − ( a / b ) × b ) y 2 = b x 2 + a y 2 − ( a / b ) × b y 2 = a y 2 + b x 2 − ( a / b ) × b y 2 \!\begin{aligned} 即ax1+by1 &= bx2 + (a - (a/b) × b)y2 \\ &=bx2 + ay2-(a/b)×by2 \\ &=ay2 + bx2-(a/b) × by2 \end{aligned} 即ax1+by1=bx2+(a−(a/b)×b)y2=bx2+ay2−(a/b)×by2=ay2+bx2−(a/b)×by2
根据恒等定理得 x 1 = y 2 , y 1 = x 2 − ( a / b ) × y 2 x1 = y2,y1 = x2 - (a/b) × y2 x1=y2,y1=x2−(a/b)×y2
利用上式,我们就可以将求 x 1 , y 1 x1,y1 x1,y1 转化为求 x 2 , y 2 x2,y2 x2,y2 。
因为 gcd \gcd gcd 不断的递归求解过程中,一定会出现 b = 0 b=0 b=0 的情况,所以递归可以结束。
我们可以得出两点:
- 必然存在满足条件的整数对 x , y x,y x,y ,原命题得证。
- 算法是正确的,且时间复杂度仅为 log \log log 级别。
代码实现
-
递归实现的代码
int exgcd(int a,int b,int &x,int &y) //最终答案存在x和y里面,函数值返回的是两数的gcd { if (b==0) //递归边界 { x=1; //可参考证明过程 y=0; //同上 return a; } int r=exgcd(b,a%b,x,y),t=x; //t是临时变量,保留x的值 x=y; //可参考证明过程 y=t-a/b*y; //同上 return r; }
-
非递归实现(无需掌握,甚至都无需了解)
int exgcd(int m,int n,int &x,int &y) //最终答案存在x和y里面,函数值返回的是两数的gcd { int x1,y1,x0,y0; x0=1; y0=0; x1=0; y1=1; x=0; y=1; int r=m%n; int q=(m-r)/n; //等同于m/n while (r) //余数不为零 { x=x0-q*x1; y=y0-q*y1; //可参考证明过程 x0=x1; y0=y1; //迭代 x1=x; y1=y; //迭代 m=n; n=r; r=m%n; q=(m-r)/n; } return n; }
后记
拓展欧几里得算法也可以用来求 a a a 膜 b b b 意义下的逆元:
- 当 gcd ( a , b ) > 1 \gcd(a,b)>1 gcd(a,b)>1 时,显然逆元不存在;
- 当
gcd
(
a
,
b
)
=
1
\gcd(a,b)=1
gcd(a,b)=1 时,可用拓展欧几里得算法求出
x
,
y
x,y
x,y 满足
a
x
+
b
y
=
gcd
(
a
,
b
)
ax+by=\gcd(a,b)
ax+by=gcd(a,b)。
在膜 b b b 的意义下,上式即为 a x ≡ 1 ( m o d b ) ax\equiv 1 \pmod b ax≡1(modb) 。所以 x x x 就是 a a a 膜 b b b 意义下的逆元。
在模数不为质数时,求逆元通常都采用这种方法。
LaTeX \LaTeX LATEX 和 M a r k d o w n \rm Markdown Markdown 打得好累啊,如果对您有帮助的话,请点个赞再走吧QAQ