欧几里得法(辗转相除法)
在扩展欧几里得之前先讲一下欧几里得法。
定理:设
a
=
q
b
+
r
a=qb+r
a=qb+r,其中
a
,
b
,
q
,
r
a,b,q,r
a,b,q,r,都是正整数,且,则有:
g
c
d
(
a
,
b
)
=
g
c
d
(
b
,
r
)
gcd(a,b)=gcd(b,r)
gcd(a,b)=gcd(b,r)
证明:
只需证明
a
a
a与
b
b
b和
b
b
b与
r
r
r有相同的最大公因子即可。设
d
d
d为
a
a
a与
b
b
b的 最大公约数,那么
d
∣
a
d|a
d∣a且
d
∣
b
d|b
d∣b。又因为
r
=
q
b
−
a
r=qb-a
r=qb−a,且
d
∣
a
,
d
∣
b
,
d|a,d|b,
d∣a,d∣b,所以
d
∣
r
d|r
d∣r。此时
a
a
a与
b
b
b的最大公约数为
d
d
d,又因为
d
∣
d|
d∣r&且
d
∣
b
d|b
d∣b,即
r
r
r与
b
b
b的最大公约数也为
d
d
d,所以上式成立。
辗转相除法:设整数 a , b , a,b, a,b,且 b ≠ 0 b≠0 b=0,做带余除法 a = q b + r a=qb+r a=qb+r,若 r = 0 r=0 r=0时, g c d ( a , b ) = b gcd(a,b)=b gcd(a,b)=b。否则 a ′ = b , b ′ = r a'=b,b'=r a′=b,b′=r;做带余除法 a ′ = q b ′ + r ′ a'=qb'+r' a′=qb′+r′,直到 r = 0 r=0 r=0时, g c d ( a , b ) = b ′ gcd(a,b)=b' gcd(a,b)=b′。由上面定理可知该法正确性。
拉梅定理:用辗转相除法计算两个正整数的最大公因子时,所需的除法次数不会超过两个整数较小的那个数的倍数的5倍。
算法实现:
int gcd(int a,int b)
{
if(b==0) return a;
return gcd(b,a%b);
}
有时也可以直接使用c语言的库函数__gcd()。
扩展欧几里得算法
定义:设a和b不全为0,则存在整数x,y,使得:
g
c
d
(
a
,
b
)
=
a
x
+
b
y
gcd(a,b)=ax+by
gcd(a,b)=ax+by
证明:
记
a
=
r
0
,
b
=
r
1
a=r_0,b=r_1
a=r0,b=r1,对
a
,
b
a,b
a,b做辗转相除法,即:
r
i
=
q
i
+
1
r
i
+
1
+
r
i
+
2
,
i
=
0
,
1
,
.
.
.
,
k
−
2
r_i=q_{i+1}r_{i+1}+r_{i+2},i=0,1,...,k-2
ri=qi+1ri+1+ri+2,i=0,1,...,k−2
r
k
−
1
=
q
k
r
k
r_{k-1}=q_kr_k
rk−1=qkrk
此时
g
c
d
(
a
,
b
)
=
r
k
gcd(a,b)=r_k
gcd(a,b)=rk,把上式改写为
r
i
=
r
i
−
2
−
q
i
−
1
r
i
+
1
,
i
=
2
,
3
,
.
.
.
,
k
r_i=r_{i-2}-q_{i-1}r_{i+1},i=2,3,...,k
ri=ri−2−qi−1ri+1,i=2,3,...,k
一直往前代入,
r
k
r_k
rk即可表示为
r
0
r_0
r0和
r
1
r_1
r1的线性组合,即
a
a
a和
b
b
b的线性组合,得证上式。
由扩展欧几里得可知整数 a a a与 b b b互质的充分必要条件:存在整数 x x x和 y y y,使得 x a + y b = 1 xa+yb=1 xa+yb=1
扩展欧几里得的算法实现由递归实现,递归边界为
b
=
=
0
,
a
=
g
c
d
(
a
,
b
)
b==0,a=gcd(a,b)
b==0,a=gcd(a,b),这时有
a
×
1
+
b
×
0
=
g
c
d
(
a
,
b
)
a\times1+b\times0=gcd(a,b)
a×1+b×0=gcd(a,b),但此时的0,1并不是需要求出的
x
,
y
x,y
x,y,只要找到每次递归
x
,
y
x,y
x,y变化的关系就可以递归求出
x
,
y
x,y
x,y的值。
我们假设
x
i
−
1
×
a
+
y
i
−
1
×
b
=
g
c
d
(
a
,
b
)
x_{i-1}\times{a}+y_{i-1}\times{b}=gcd(a,b)
xi−1×a+yi−1×b=gcd(a,b),那么
x
i
×
b
+
y
i
×
a
%
b
=
g
c
d
(
b
,
a
%
b
)
x_i\times{b}+y_i\times{a\%b}=gcd(b,a\%b)
xi×b+yi×a%b=gcd(b,a%b),
x
i
x_i
xi为第
i
i
i次递归
x
x
x的值,
x
0
x_0
x0即为所求的
x
x
x。
因为
a
%
b
=
a
−
(
a
b
)
×
b
a\%b=a-(\frac{a}{b})\times{b}
a%b=a−(ba)×b,代入可得:
x
i
×
b
+
y
i
×
(
a
−
(
a
b
)
×
b
)
=
g
c
d
(
b
,
a
%
b
)
x_i\times{b}+y_i\times{(a-(\frac{a}{b})\times{b}})=gcd(b,a\%b)
xi×b+yi×(a−(ba)×b)=gcd(b,a%b)
b
×
(
x
i
−
a
b
×
y
i
)
+
y
i
×
a
=
g
c
d
(
a
,
b
)
b\times{(x_i-\frac{a}{b}\times{y_i})}+y_i\times{a}=gcd(a,b)
b×(xi−ba×yi)+yi×a=gcd(a,b)
所以
x
i
−
1
=
y
i
,
y
i
−
1
=
x
i
−
a
b
×
y
1
x_{i-1}=y_i,y_{i-1}=x_i-\frac{a}{b}\times{y1}
xi−1=yi,yi−1=xi−ba×y1
算法实现:
int exgcd(int a,int b,int&x,int&y)
{
if(b==0)
{
x=1,y=0;
return a;
}
else
{
int r=gcdEx(b,a%b,x,y); //r=GCD(a,b)=GCD(b, a%b)
int t=x;
x=y;
y=t-a/b*y ;
return r ;
}
}
扩展欧几里得算法的应用主要有三方面:
1.求解不定方程。
2.求解模的逆元。
3.求解同余方程。
这里简单介绍以下求解模的逆元:
如果
a
×
x
≡
1
(
m
o
d
p
)
a\times{x}≡1 (mod\ p)
a×x≡1(mod p),且
g
c
d
(
a
,
p
)
=
1
gcd(a,p)=1
gcd(a,p)=1,即
a
a
a与
p
p
p互质,则称
a
a
a关于模
p
p
p的乘法逆元为
x
x
x。
设
a
×
x
=
1
(
m
o
d
p
)
a\times{x}=1(mod\ p)
a×x=1(mod p),即:
a
×
x
−
m
×
p
=
1
\ \ \ \ \ \ \ \ \ \ \ \ a\times{x}-m\times{p}=1
a×x−m×p=1 (
m
m
m为整数)
其中gcd(a,p)=1,即求解
x
,
p
x,p
x,p,设
b
=
p
,
y
=
m
b=p,y=m
b=p,y=m,即求解
g
c
d
(
a
,
b
)
=
a
x
+
b
y
gcd(a,b)=ax+by
gcd(a,b)=ax+by
求出
x
x
x即为
a
a
a关于模
p
p
p的乘法逆元。