欧几里得算法和扩展欧几里得算法——杨子曰数学

欧几里得算法和扩展欧几里得算法——杨子曰数学

超链接:数学合集


不说废话,咱们直接开始

欧几里得算法

一句话:
g c d ( a , b ) = g c d ( b , a   m o d   b ) gcd(a,b)=gcd(b,a\ mod\ b) gcd(a,b)=gcd(b,a mod b)
简单证明:

首先我们先来证一证这个: g c d ( a , b ) = g c d ( b , a − b ) gcd(a,b)=gcd(b,a-b) gcd(a,b)=gcd(b,ab)

假设: d = g c d ( a , b ) , a = k a ∗ d , b = k b ∗ d ( k a 和 k b 互 质 ) d=gcd(a,b),a=k_a*d,b=k_b*d(k_a和k_b互质) d=gcd(a,b),a=kad,b=kbdkakb

这样一来,我们会发现:
a − b = k a ∗ d − k b ∗ d = ( k a − k b ) ∗ d a-b=k_a*d-k_b*d=(k_a-k_b)*d ab=kadkbd=(kakb)d
欧,有没有发现a-b和b还是都有公因子d

a − b = ( k a − k b ) ∗ d a-b=(k_a-k_b)*d ab=(kakb)d

b = k b ∗ d b=k_b*d b=kbd

BUT,我们还要证明d是它们的最大公因子,也就是要证明,它们的系数 k a − k b k_a-k_b kakb k b k_b kb的互质(它们如果不互质,那么最大公因数就会变成 d ∗ g c d ( k a − k b , k b ) d*gcd(k_a-k_b,k_b) dgcd(kakb,kb)

我们用反证法:

假设 k a − k b k_a-k_b kakb k b k_b kb不互质

设 : g c d ( k a − k b , k b ) = λ ( λ > 1 ) , k a − k b = α ∗ λ , k b = β ∗ λ 设:gcd(k_a-k_b,k_b)=\lambda(\lambda>1),k_a-k_b=\alpha*\lambda,k_b=\beta*\lambda :gcd(kakb,kb)=λλ>1kakb=αλkb=βλ
于是
k a = k a − k b + k b = α ∗ λ + β ∗ λ = ( α + β ) ∗ λ k_a=k_a-k_b+k_b=\alpha*\lambda+\beta*\lambda=(\alpha+\beta)*\lambda ka=kakb+kb=αλ+βλ=(α+β)λ

有没有发现 k a k_a ka k b k_b kb有了公因数 λ \lambda λ,别忘了上面还有一个条件叫 k a 和 k b 互 质 k_a和k_b互质 kakb

于是得证!

然后我们就得到了: g c d ( a , b ) = g c d ( b , a − b ) gcd(a,b)=gcd(b,a-b) gcd(a,b)=gcd(b,ab)

然后,我们把a-b看成等式左边新的b,然后一直拿a减,直到不能减了为止,其实就是:
g c d ( a , b ) = g c d ( b , a   m o d   b ) gcd(a,b)=gcd(b,a\ mod\ b) gcd(a,b)=gcd(b,a mod b)

得证!


int gcd(int a,int b){
	return b==0?a:gcd(b,a%b);
}

扩展欧几里得算法

这个东西只有一个作用
求 a x + b y = g c d ( a , b ) 的 整 数 解 求ax+by=gcd(a,b)的整数解 ax+by=gcd(a,b)

假设存在一组x’和y’使得:
b x ′ + ( a   m o d   b ) y ′ = g c d ( b , a   m o d   b ) bx'+(a\ mod\ b)y'=gcd(b,a\ mod\ b) bx+(a mod b)y=gcd(b,a mod b)

根据上面的欧几里得算法:
g c d ( a , b ) = g c d ( b , a   m o d   b ) gcd(a,b)=gcd(b,a\ mod\ b) gcd(a,b)=gcd(b,a mod b)

我们就得到了:
a x + b y = b x ′ + ( a   m o d   b ) y ′ ax+by=bx'+(a\ mod\ b)y' ax+by=bx+(a mod b)y

幼儿园小盆友都知道:
a   m o d   b = a − ⌊ a b ⌋ ∗ b a\ mod\ b=a-\lfloor\frac{a}{b}\rfloor*b a mod b=abab

然后把它带回去:
a x + b y = b x ′ + ( a − ⌊ a b ⌋ ∗ b ) y ′ ax+by=bx'+(a-\lfloor\frac{a}{b}\rfloor*b)y' ax+by=bx+(abab)y

把括号拆开:
a x + b y = b x ′ + a y ′ − ⌊ a b ⌋ ∗ b y ′ ax+by=bx'+ay'-\lfloor\frac{a}{b}\rfloor*by' ax+by=bx+aybaby

再合并一下:
a x + b y = a y ′ + b ( x ′ − ⌊ a b ⌋ ∗ y ′ ) ax+by=ay'+b(x'-\lfloor\frac{a}{b}\rfloor*y') ax+by=ay+b(xbay)

So,你有没有惊奇的发现一定有一组解长这样:
{ x = y ′ y = x ′ − ⌊ a b ⌋ ∗ y ′ \left\{ \begin{aligned} x&=y'\\ y&=x'-\lfloor\frac{a}{b}\rfloor*y' \end{aligned} \right. xy=y=xbay

也就是说我们只要求出x’和y’就可以求出x和y了

我们再来回头看一下它们的方程:
a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)

b x ′ + ( a   m o d   b ) y ′ = g c d ( b , a   m o d   b ) bx'+(a\ mod\ b)y'=gcd(b,a\ mod\ b) bx+(a mod b)y=gcd(b,a mod b)
有没有发现形式是一样滴,So,我们可以通过递归来解决它

那么临界情况是什么捏?

一个幼儿园小盆友都知道的事实:
g c d ( a , 0 ) = a gcd(a,0)=a gcd(a,0)=a
So,当b=0时:
a x + 0 = g c d ( a , 0 ) ax+0=gcd(a,0) ax+0=gcd(a,0)
然后就可以,美滋滋地让x=1,y是任意值了(一般是0,它会影响最后的解的大小)

OK,完事

void ex_gcd(int a,int b,int &x,int &y){
    if(!b) x=1,y=0;
    else ex_gcd(b,a%b,y,x),y-=(a/b)*x;
}

应用1:解方程ax+by=c

首先,在上面已经讲过了,扩展欧几里得可以求长这样的方程:
a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)
那有什么卵用!我从来没有在哪道题里见长成这样的方程

BUT,我们可以利用它来解长成这样的方程:
a x + b y = c ax+by=c ax+by=c
d = g c d ( a , b ) d=gcd(a,b) d=gcd(a,b)
这时,如果我们把这个方程同时乘上一个 d c \frac{d}{c} cd

方程就变成了:
a d c ∗ x + b d c ∗ y = g c d ( a , b ) a\frac{d}{c}*x+b\frac{d}{c}*y=gcd(a,b) acdx+bcdy=gcd(a,b)

我们就可以来解一个这样的方程:

a x ′ + b y ′ = g c d ( a , b ) ax'+by'=gcd(a,b) ax+by=gcd(a,b)

于是你就会发现,原方程的解就是:
{ x = x ′ ∗ c d y = x ′ ∗ c d \left\{ \begin{aligned} x&=x'*\frac{c}{d}\\ y&=x'*\frac{c}{d} \end{aligned} \right. xy=xdc=xdc

你一定会问了c如果不是d的倍数肿么办?

那就没有整数解呗!这有什么好问的?

应用2:解模线性方程: a x ≡ b ( m o d   p ) ax\equiv b(mod\ p) axb(mod p)

其实就是应用1,有没有发现 a x ≡ b ( m o d   p ) ax\equiv b(mod\ p) axb(mod p),就是: a x + p y = b ax+py=b ax+py=b,然后再用上面的那个东东解出来就好了
解模线性方程,就可以做很多事情了,比如:求逆元,戳我

参考:
https://www.zybuluo.com/samzhang/note/541890
于HG机房

你可能感兴趣的:(崩溃的数学)