小学二年级都能看懂的扩展欧几里得学习笔记

一些闲扯

上次学扩展欧几里得是两年前,结果中考复习期间不动电脑,直接忘得一干二净
然后两个月前又看了一遍,今天要用的时候发现还是不熟练(看了个寂寞属于是)
别人化身狂暴切题组长的时候我在复习
而且网上的一大堆博客看得我晕晕乎乎费老大劲才彻底搞明白,这时其他人已经a了三四道了orz
于是下定决心开了个blog,直接自己写一个小学二年级都能看懂的学习笔记,这样我再忘掉知识点的时候就直接看这篇就能秒懂了罢(希望)
这是本人第一篇blog,不知写得怎么样(虽然写得差我也改不了)

前置算法——欧几里得(辗转相除)

计算a与b的最大公约数\(gcd(a,b)\)

\(r=a\bmod b,k=\left \lfloor \frac{a}{b} \right \rfloor,d=gcd(a,b)\)

\(r=a-kb\)

\(d|a,d|b\)

所以 \(d|r\)

同理,令 \(gcd(b,a\bmod b)=d',d'|r,d'|b\)

所以 \(d'|kb+r,d'|a\)

\(gcd(a,b)=gcd(b,a\bmod b)\)

递归下去,直到 \(a'=d,b'=0\)

此时 \(gcd(a,b)=gcd(a',b')=d\)

代码如下,非常简单:

void gcd(ll a,int b){
	if(!b){
		return a;
	}
	return gcd(b,a%b);
}

拓展欧几里得

介绍

总之就是求解不定方程 \(ax+by=c\)

直接讲方法

原理

首先考虑证明对于 \(ax+by=c\) ,方程有整数解的充要条件为 \(gcd(a,b)|c\)

首先证明必要性,这非常简单。

因为 \(x,y\) 均为整数

所以 \(gcd(a,b)|ax+by\)

所以 \(gcd(a,b)|c\)

接下来证明充分性,而这就涉及到裴蜀定理

裴蜀定理

裴蜀定理内容如下:设 \(a,b\) 是不全为零的整数,则存在整数 \(x,y\) , 使得 \(ax+by=gcd(a,b)\) .

说人话就是当 \(ax+by=gcd(a,b)\) 时必然有解,当 \(gcd(a,b)|c\) 的时候自然也有解
(直接解出来 \(ax+by=gcd(a,b)\) 再乘上 \(\frac{c}{gcd(a,b)}\) 就好了)

证明如下:

\(s\)\(ax+by\) 的最小正值, \(q=\left \lfloor \frac{a}{s} \right \rfloor,r=a\bmod s\)

显然 \(0\leq r<s\)\(r=a-s*q=a-(ax+by)*q=a(1-qx)+b(-qy)\)

可见 \(r\) 也为 \(a,b\) 的线性组合

又因为 \(s\)\(ax+by\) 的最小正值且 \(0\leq r<s\)

也就是说,在 \((0,s)\) 范围内不可能存在 \(r\) 满足 \(ax+by=r\)

所以 \(r\) 只能等于 \(0\),即 \(a\bmod s=0\)

所以 \(s|a\) ,同理 \(s|b\)

\(d=gcd(a,b)\)

由于 \(s\)\(ax+by\) 最小正值,所以 \(s\leq d\)

由于 \(ax+by=c\) 有解的必要条件为 \(gcd(a,b)|c\)

所以 \(d|s\) ,即 \(d\leq s\)

所以 \(s=d=gcd(a,b)\)

证毕

解方程

在证明了上面的结论后,我们就可以尝试解决 \(ax+by=c\)

首先由于只有 \(gcd(a,b)|c\) 时方程有解,不妨先解出方程 \(ax+by=gcd(a,b)\) ,再将解乘上 \(\frac{c}{gcd(a,b)}\) 即可

对于

\[\begin{aligned} ax+by&=gcd(a,b) \\&=gcd(b,a \bmod b) \\&\Rightarrow bx_1+(a \bmod b)y_1 \\&=bx_1+(a-\lfloor \frac{a}{b}\rfloor \cdot b)y_1 \\&=ay_1+b(x_1+\lfloor \frac{a}{b}\rfloor y_1) \end{aligned} \]


上面一部分或许有点绕。简而言之,我们列出了两个方程:

\(ax+by=gcd(a,b)\)\(bx_1+(a\bmod b)y_1=gcd(b,a\bmod b)\)

根据 \(gcd(a,b)=gcd(b,a \bmod b)\)

可得 \(ax+by=bx_1+(a\bmod b)y_1\)

然后将右边表示成 \(ay_1+b(x_1+\lfloor \frac{a}{b}\rfloor y_1)\) 的形式

由于 \(ax+by=ay_1+b(x_1+\lfloor \frac{a}{b}\rfloor y_1)\)

不难发现,如果知道 \(x_1,y_1\) ,则原方程必有一组满足条件的解 \(x=y_1,y=x_1+\lfloor \frac{a}{b}\rfloor y_1\)

而为了解出 \(x_1,y_1\) ,我们可以仿照欧几里得求最大公因数的过程,递归下去,解出 \((a \bmod b)x_2+(b\bmod (a\bmod b))y_2=gcd(a,b)\) 中的 \(x_2,y_2\)

以此类推解出 \(x_3,y_3,x_4,y_4……\)

我们假设我们得到这么一个方程 \(a'x_n+b'y_n=gcd(a,b)\)

根据前面欧几里得算法可得知,当 \(b'=0\) 时, \(a'=gcd(a,b)\)

此时原方程可表示为 \(gcd(a,b)\cdot x_n+0y_n=gcd(a,b)\)

显然此方程有一组解 \(x_n=1,y_n=0\)

将其递归回去,即可解出 \(x,y\)

代码也是非常简单

void exgcd(ll a,int b,ll &x,ll &y){
	if(!b){
		x=1,y=0;
	}
	else{ 
		exgcd(b,a%b,y,x);//此时 x=y1,即为方程的解,y=x1
		y-=x*(a/b); //此时 y=y-x*(a/b)=x1-y1*(a/b) 为方程的解
	}
}
posted @ 2022-09-05 23:06  万航之舰  阅读(189)  评论(0)    收藏  举报