欧几里德算法 && 扩展欧几里德算法【超级详解,保证您看不了吃亏,看不了上当】

博客介绍了欧几里德算法(辗转相除法),用于求整数a、b的最大公因数,给出算法内容、证明及代码。还阐述了扩展欧几里德算法,输入a、b求整数x、y使ax + by = gcd(a, b)成立,同时说明了已知方程一组解求通解的方法及相关结论。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

欧几里德算法:(辗转相除法)

求整数a、b (a>b) 的最大公因数(Greatest Common Divisor):

算法内容

假设整数a>=b

  1. a / b = q1 … r1
  2. 如果 r1=0,gcd(a,b)=b;
  3. 如果 r1!=0,b / r1 = q2 … r2;
  4. 如果 r2=0,gcd(a,b)=r1;
  5. 如果 r2!=0,r1 / r2 = q3 … r3;
  6. ……
  7. 以此往复,直到最后余数为0的除数即为gcd(a,b)

证明
我们假设整数a / b = q … r (a>=b),显然有b>r
转换一下得到:a = bq + r
现在我们假设c为a和b的一个公因数,即 c | a,c | b (意为c是b的一个因子)
于是我们可以设:a= cm; b= cn;
将a,b带到 a = bq + r 里去,得到:cm=cnq+r
移项合并可以得到:c(m-nq) = r,即 c | r
推得:所有a和b的公因子都是b和r的公因子

同理:所有b和r的公因子都是a和b的公因子

于是得到结论:gcd(a,b)=gcd(b,r)=gcd(b,a%b)

code

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

最小公倍数(Lowest Common Multiple)

因为:

gcd(a,b)*lcm(a,b)=a*b

所以:

lcm(a,b)=a/gcd(a,b)*b;//为了防止a*b溢出,所以先除后乘

扩展欧几里德算法:

输入 a,b ,求整数 x,y 使得 ax+by=gcd(a,b) 成立。

内容+证明:

  1. 假设b*x1+(a%b)*y1=gcd(b,a%b)已经求出(x1,y1)
  2. 由欧几里德算法可知gcd(a,b)=gcd(b,a%b)
  3. 所以可以得到a*x+b*y=b*x1+(a%b)*y1
  4. 因为a%b=a-(a/b)*b
  5. 所以a*x+b*y=b*x1+(a-(a/b)*b)*y1
  6. 所以a*x+b*y=a*y1+b(x1-(a/b)*y1)
  7. 所以:x=y1; y=b(x1-(a/b)*y1);

那么显然我们可以借助欧几里德通过递归来求出(x,y)

code:

int x,y;
int exgcd(int a,int b)
{
    if(!b)
    {
        x=1;
        y=0;
        return a;
    }
    int d=exgcd(b,a%b);
    int tx=y;
    int ty=x-(a/b)*y;
    x=tx;
    y=ty;
    return d;
}

部分代码解释:
d=exgcd(b,a%b);
跑完这一步,(x,y)实际上被赋值为(x1,y1),所以我们要通过推得的式子来得到初始我们要求的(x,y)

已知方程ax+by=c的一组解(x0,y0),我们如何求方程通解?

首先,我们先考虑求一组(x0,y0)的相邻的解(x1,y1)
x1=x0+i
y1=[ a*(x0+i)-c ] / (-b)=(ax0-c) / (-b) +a*i / (-b)= y-a*i/b
因为我们要求整数解,所以要保证a*i / bi都是整数;又因为我们要求的是相邻解,所以我们要在i是整数的前提下使a*i / b尽可能小
一、可以分两种情况来考虑:

  1. 如果a和b互质,那么有且仅有i=b能使a*i / b为整数且最小
  2. 如果a和b不互质,那么就先使a*i / b化简,上下同时除以gcd(a,b),使分子分母互质,即(a/gcd(a,b))*i / b/gcd(a,b),这个时候i=b/gcd(a,b)才能满足条件
  3. 综合上面两种情况,只有当i=b/gcd(a,b)时,(x1,y1)为(x0,y0)的相邻解,即x1=x0+b/gcd(a,b) y1=y0-a/gcd(a,b)

二、我们要在i是整数的前提下使a*i / b尽可能小,所以a*i=lcm(a,b),所以i=lcm(a,b)/a=a*b/gcd(a,b)/a=b/gcd(a,b)也就是i=b/gcd(a,b),和上面得出的结果是一样的

由于方程是线性的,所以整数解满足线性关系,所以通解为:

x[k]=x0+k*b/gcd(a,b)
y[k]=y0-k*a/gcd(a,b)

另外:

设,a,b,c是任意整数,g=gcd(a,b),方程 ax+by=g 的一组解是(x0,y0),则当c是g的倍数时,ax+by=c 的一组解是(x0c/g,y0c/g);当c不是g的倍数时无整数解。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值