欧几里得与扩展欧几里得算法

欧几里得

它是我们求解整数 a,b 的最大公约数的算法。

前置知识

max(a,b)+min(a,b)=a+b

max(a,b)=a+bmin(a,b),min(a,b)=a+bmax(a,b)

过程

不妨设 a>b

我们发现如果 ba 的约数,那么 b 就是 a,b 的最大公约数,现在考虑 b 不是 a 的约数时的情况。

a=b×q+r,其中 r<b,我们可以通过证明 gcd(a,b)=gcd(b,amodb)

此时显然有 r=amodb,则 r=ab×q,设 d|a,d|b,则 rd=adbdq

由右边式子可知 rd 为整数,即 d|r ,所以对于 a,b 的公约数,它也会是 b,amodb 的公约数。

反过来也需证明,设 d|amodb,d|b,则 amodbd+bdq=ad,由左边式子可知 ad 为整数,即 d|a,所以 b,amodb的公约数也会是 a,b 的公约数。

既然两式的公约数相同,则两式的最大公约数也一定相同。

所以得到式子 gcd(a,b)=gcd(b,amodb)

注:根据以上说明,可知两个数的最大公约数的约数一定包含两个数的公约数

代码

int gcd(int a, int b) {
  while (b != 0) {
    int tmp = a;
    a = b;
    b = tmp % b;
  }
  return a;
}

多个数的最大公约数

显然答案是每个数的约数,那么也一定等于每相邻两个数的约数,那么我们每次取出两个数求出它们的最大公约数,再放回去,然后删除这两个数,此时这个公约数就包含了两个数的所有约数。 直至剩下的数的个数为 1 ,就停止。

最小公倍数

两个数

根据算术基本定理,设 a=p1ka1p2ka2...pskas,b=p1kb1p2kb2...pskbs

我们发现两者的最大公因数为:

p1min(ka1,kb1)p2min(ka2,kb2)...psmin(kas,kbs)

最小公倍数为:

p1max(ka1,kb1)p2max(ka2,kb2)...psmax(kas,kbs)

由于 ka+kb=max(ka,kb)+min(ka,kb)

所以得到的结论为 gcd(a,b)×lcm(a,b)=a×b

根据结论,先求出两数的最大公因数,再求出两数的最小公倍数即可。

多个数

对于一个数列 a1,a2,...,an ,所以 a1=p1b11p2b12...psb1s,a2=p1b21p2b22...psb2s...,an=p1bn1p2bn2...psbns ,还是一样,假设现在处理到第i个数,前i1个数的最小公倍数为 m ,很显然 m=p1max(b11,b21,...,bi11)p2max(b12,b22,...,bi12)...psmax(b1s,b2s,...,bi1s)ai=p1bi1p2bi2...psbis,所以前 i 个数的最小公倍数应为 m1=p1max(b11,b21,...,bi1)p2max(b12,b22,...,bi2)...psmax(b1s,b2s,...,bis) ,我们发现 gcd(m,ai)=p1min(max(b11,b21,...,bi11),bi1)p2min(max(b12,b22,...,bi12),bi2)...psmin(max(b1s,b2s,...,bi1s),bis)

m×ai=p1max(b11,b21,...,bi11)+bi1p2max(b12,b22,...,bi12)+bi2...psmax(b1s,b2s,...,bi1s)+bis

m×ai÷gcd(m,ai)=p1max(b11,b21...,bi11)+bi1min(max(b11,b21,...,bi11),bi1)...psmax(b1s,b2s...,bi1s)+bismin(max(b1s,b2s,...,bi1s),bis)

max(b11,b21...bi11)bi1时,max(b11,b21...,bi11)+bi1min(max(b11,b21,...,bi11),bi1)=bi1

反之有max(b11,b21...,bi11)+bi1min(max(b11,b21,...,bi11),bi1)=max(b11,b21...,bi11)

所以最终结果均满足是最大值,故得证。

方法二:

m×ai÷gcd(m,ai)=p1max(b11,b21...,bi11)+bi1min(max(b11,b21,...,bi11),bi1)...psmax(b1s,b2s...,bi1s)+bismin(max(b1s,b2s,...,bi1s),bis)

max(b11,b21...,bi11)+bi1min(max(b11,b21,...,bi11),bi1)max(b11,b21...,bi11) 看作 Abi1 看作 B ,则原式化为 A+Bmin(A,B) 根据前置知识可知 max(A,B)=A+Bmin(A,B)

故得证。

代码如下:

int gcd(int a,int b)
{
    if(!b)return a;
    return gcd(b,a%b);
}
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
int m=a[1];
for(int i=2;i<=n;i++)
    m=m*a[i]/gcd(m,a[i]);

裴蜀定理

对于任意正 整数 a ,b,存在一对整数 x,y ,满足 ax+by=gcd(a,b)

感性理解一下,我们发现因为 x,y 为整数,所以 ax+bygcd(a,b) 的倍数,所以一定存在一组 x,y 使得 ax+by=gcd(a,b)

那么感性理解完毕,我们开始证明。

d=gcd(a,b),则 ax+by=ad×d×x+bd×d×y=cd×d

两边去掉 d 得:ad×x+bd×y=cd,因为 ad 为整数,bd 也为整数, x,y 也为整数,根据“整数 × 整数 = 整数,整数 + 整数 = 整数”的封闭法则cd 一定为整数,也就是 d|a

故得证。

扩展欧几里得

它是一般我们求解形如 ax+by=c 的方程时的算法。

根据裴蜀定理,我们可以很轻松地知道 gcd(a,b)|c 时才会有整数解。

ax1+by1=gcd(a,b)

bx2+(amodb)y2=gcd(b,amodb)

由欧几里得定理可知 gcd(a,b)=gcd(b,amodb)

所以 ax1+by1=bx2+(amodb)y2

又因为 amodb=aab×b

所以上式化为: ax1+by1=bx2+(aab×b)y2

所以:ax1+by1=bx2+ay2ab×b×y2=ay2+b×(x2ab×y2)

假设我们已经先求出了 x2,y2,因为 a=a,b=b,则 x1=y2,y1=(x2ab×y2).

所以求解这种问题就可以转化成求解最大公约数的过程了。

注:边界情况当 b=0 时,所以 gcd(a,b)=aax+by=gcd(a,b)=a

则原式化为:ax=a,则 x=1,y 取任意实数,但一般如果你不想爆 long  long 的话,最好是 y=0

代码

int Exgcd(int a, int b, int &x, int &y) {
  if (!b) {
    x = 1;
    y = 0;
    return a;
  }
  int d = Exgcd(b, a % b, x, y);
  int t = x;
  x = y;
  y = t - (a / b) * y;
  return d;
}

例题:青蛙的约会

显然,青蛙A走的路程为x+km,青蛙B走的路程为y+kn,则题意要求x+kmmodL=y+knmodL,即x+kmy+kn(modL)

将上式化为一般方程为:k(mn)+zL=yx,因为m,n,L,y,x都是已知量,所以这个方程就相当于关于k,z的二元一次不定方程。

Code

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int exgcd(int a,int b,LL &x,LL &y){
    if(b==0){
        x=1,y=0;
        return a;
    }
    int d=exgcd(b,a%b,y,x);
    y-=a/b*x;
    return d;
}
int main(){
    int a,b,m,n,l,f;
    //cin>>f;
    //while(f--){
        cin>>a>>b>>m>>n>>l;
        LL x=0,y=0;
        int d=exgcd(m-n,l,x,y);
        if((b-a)%d!=0){
            cout<<"Impossible"<<endl;
        }else{
            int t3=b-a;
            x=x*t3/d;
            y=y*t3/d;
            int t=abs(l/d);
            cout<<(x+t)%t<<endl;
        }
    //}
    return 0;
}
posted @   wangyuanbo  阅读(6)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示