欧几里得与拓展欧几里得算法学习笔记

欧几里得与拓展欧几里得

欧几里得算法

欧几里得算法是一种快速求出最大公约数的算法。

内容

对于任意的两个整数 \(a,b\),其最大公约数 \(\gcd(a,b) = \gcd(b,a \bmod b)\)

证明

  • 对于 \(b>a\) 的情况 ,显然成立。
  • 因此只考虑 \(b<a\) 的情况。设 \(a=q \times b +p,\left( q=\left\lfloor\dfrac{a}{b}\right\rfloor,p=a-b \times\left\lfloor\dfrac{a}{b}\right\rfloor=a\bmod b \right)\)
    • 对于 \(g_1=\gcd(a,b)\),显然存在 \(g_1\mid a,g_1\mid b\),由此易得 \(g_1\mid p\),其中\(\ g_1\mid a\) 表示 $a \bmod g_1 =0\ $。
    • 又因为 \(p=a\bmod b\),所以对于 \(a,b\) 的最大公约数 \(g_1\),同样满足 \(g_1\mid a\bmod b,g_1\mid b\),即 \(b,a\bmod b\) 的最大公约数至少为 \(g_1\),即 \(\gcd(b,a \bmod b) > g1=\gcd(a,b)\)
    • 反过来,对于 \(b,a\bmod b\) 的最大公约数 \(g_2=\gcd(b,a\bmod b)\),同样满足 \(g_2 \mid a,g2 \mid b\),即 \(\gcd(a,b)>g2=\gcd(b,a \bmod b)\)
  • 因此 \(\gcd(a,b)=\gcd(b,a \bmod b)\) 证明成立。

代码实现

#include <bits/stdc++.h>
using namespace std;
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int main(){
	int a,b;cin>>a>>b;
	cout<<gcd(a,b)<<endl;return 0;
}

拓展欧几里得算法

内容

求解不定方程 $$ax+by=\gcd(a,b)$$

证明

令 $$a\ x_1+b\ y_1=\gcd(a,b)$$

\[b\ x_2+(a \bmod b)y_2=\gcd(b,a \bmod b) \]

根据欧几里得算法可知 $$\gcd(a,b)=\gcd(b,a\bmod b)$$
所以可得 $$a\ x_1+b\ y_1=b\ x_2+(a \bmod b)\ y_2=b\ x_2+ \left(a\ –\ b \ \left\lfloor\dfrac{a}{b}\right\rfloor \right) y_2=a\ y_2+b\ x_2-b^2\ \left\lfloor\dfrac{a}{b}\right\rfloor y_2$$
解得:\(\begin{cases}x_1=y_2 \\ y_1=x_2-\left\lfloor\dfrac{a}{b}\right\rfloor y_2\end{cases}\)
即方程的一组解。

代码实现

P1082 [NOIP2012 提高组] 同余方程

求关于 \(x\) 的同余方程 \(ax \equiv 1 \pmod{b}\) 的最小正整数解。

直接套板子即可。

#include <bits/stdc++.h>
using namespace std;int k,x,y;
void exgcd(int a,int b){
    if(b==0){x=1;y=0;return;}
    exgcd(b,a%b);k=x;x=y;y=k-a/b*y;return;
}int main(){
    int n,m;cin>>n>>m;exgcd(n,m);
    cout<<(x+m)%m<<endl;return 0;
}
posted @ 2022-05-09 12:24  AIskeleton  阅读(19)  评论(0编辑  收藏  举报