欧几里得
欧几里得是用来求gcd(a,b)的
也就是我们一般所说的辗转相除法
gcd(a,b)=gcd(b,a%b)
证明:
设a=k
∗
∗
n,b=km,且n,m互质
那么gcd(a,b)=k;
设a/b=t,
那么gcd(b,a%b)=gcd(k
∗
∗
m,kn-k
∗
∗
mt)=gcd(k
∗
∗
m,k(n-m
∗
∗
t)
因为n与m互质,那么n减去一个m的倍数也一定与m互质,所以gcd(b,a%b)=k;
结论得证
扩展欧几里得
解不定方程ax+by=gcd(a,b)
首先证明ax+by=p,p!=gcd(a,b)一定无解
先两边同除使得a,b,p不存在大于1的公约数
方程为x+
b1
b
1
y=
p1
p
1
设此时gcd(
a1
a
1
,
b1
b
1
)=q;
那么
a1
a
1
,
b1
b
1
一定是q的倍数,所以等式左边一定是q的倍数,而
a1
a
1
,
b1
b
1
,
p1
p
1
没有大于1的公约数,所以等式右边一定不是q的倍数,所以一定无解。
那么接下来就是求解ax+by=gcd(a,b)的过程
首先当b=0时,x=1,y=0,这也是程序递归实现的出口
假设a
x1
x
1
+b
y1
y
1
=gcd(a,b)
b
x2
x
2
+a%b
∗
∗
=gcd(b,a%b)
通过欧几里得我们知道gcd(a,b)=gcd(b,a%b)
所以a
x1
x
1
+b
y1
y
1
=b
x2
x
2
+a%b
∗
∗
把式子换个表示方法a
x1
x
1
+b
y1
y
1
=b
x2
x
2
+a-a/b*b
∗
∗
提取公因式a
x1
x
1
+b
y1
y
1
=b
∗
∗
(-a/b*
y2
y
2
)+a
y2
y
2
;
由于两边恒等
所以_
x1
x
1
=
y2
y
2
,
y1
y
1
=
x2
x
2
-a/b
∗
∗
程序实现
int exgcd(int a,int b,int &x,int &y){
if (b==0){
x=1;
y=0;
return a;
}
int tt=exgcd(b,a%b,y,x);
y-=a/b*x;
return tt;
}
这里再讲一下如何用扩展欧几里得来求一个数的逆元
相当于求解同余方程ax≡1 (mod p)
转化一项相当于是求ax-p
∗
∗
<script type="math/tex" id="MathJax-Element-50">*</script>y=1
当gcd(a,p)=1时该方程有解,(将p的负号给y就可以了),然后得出x的值,把范围调整到0~m-1就好了,就是a在模p意义下的乘法逆元了。
如果文章里有什么写的不对或者描述不清的,欢迎在评论中指出,感激不尽