扩展欧几里得算法总结和例子

扩展欧几里得算法

如果a、b是整数,那么一定存在整数x、y使得ax+by=gcd(a,b)
换句话说,如果ax+by=m有解,那么m一定是gcd(a,b)的若干倍。(可以来判断一个这样的式子有没有解)
若gcd(a,b) | c,则方程有解,否则无解。

int gcd(int a,int b)//求a和b的最小公约数
{
    return b==0?a:gcd(b,a%b);
    
    
    //或者:
    int gcd(int a,int b)
{
    int c;
    while(a%b!=0) {
        c=a%b;
        a = b;
        b = c;
    }
    return b;
}

扩展欧几里得

递归结束的条件:当到达递归边界的时候,b==0,a=gcd(a,b) 这时可以观察出来这个式子的一个解:a1+b0=gcd(a,b),x=1,y=0,注意这时的a和b已经不是最开始的那个a和b了,所以我们如果想要求出解x和y,就要回到最开始的模样
注意在递归算法中,永远都是先得到下面一个状态的值
首先我们知道:a%b=a-(a/b)b;带入:
b
x1 + (a-(a/b)b)y1
= b
x1 + a
y1 – (a/b)by1
= ay1 + b(x1 – a/by1) = gcd 发现 x = y1 , y = x1 – a/b*y1
解法:
先运用扩展欧几里得算法求出ax + by = gcd(a,b) 一组特解x0,y0则通解:
x = x0 + b/gcd(a,b) * t
y = y0 - a/gcd(a,b) * t
对应方程 ax + by = c只需要在通解基础上乘以一个比例系数:c/gcd(a,b)

例如:3x+4y=2
利用exgcd算出3x+4y=gcd(3,4)的解x=-1,y=1;
则原式的解为x
2/gcd(3,4),y2/gcd(3,4);
求最小正整数解:
使用拓展欧几里德找到ax+by=c的一组整数解(x0,y0)之后,
k=b/gcd(a,b),x’=(x0%k+k)%k,y’=(c-ax)/b,就可以得到x的最小正整数解。
同理,令k=a/gcd(a,b),y’=(y0%k+k)%k,x’=(c-by)/a,就可以得到y的最小正整数解。
解模线性方程
ax ≡ b (mod p)
先对方程进行转换 (ax - b) = -y
p 根据同余的性质ax与b的差是模数的倍数
移项可知: ax + py = b

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int exgcd(int a,int b,int &x,int &y)//扩展欧几里得算法ax+by=c;
{
    if(b==0)
    {
        x=1;y=0;
        return a;  //到达递归边界开始向上一层返回
    }
    int r=exgcd(b,a%b,x,y);
    int temp=y;    //把x y变成上一层的
    y=x-(a/b)*y;
    x=temp;
    return r;     //得到a b的最大公因数
}
//返回的是a和b的最小公倍数
//而x和y的值则直接得到改变
//而且 根据公式可以得到通解
//x = x0 + b*t;
//y = y0 - a*t;(t为任意常数)

遇到的方程的格式可能不适用于欧几里得算法,需要我们自己移项
例如:(x+mt)-(y+nt)=kl
移项并合并同类项:
(x-y)+(m-n)t=kl
再移项,变为扩展欧几里得的一般形式:
k
l+(n-m)*t = x-y
我们和一般形式对比一下,得a=l,b=(n-m),x1=k,y1=t,d=x-y
这里要注意,设c=GCD(a,b),扩展欧几里得有解的条件是d % c== 0,而后面这个x-y不一定是c的倍数。
例题:https://blog.youkuaiyun.com/wyg1997/article/details/52085958

### 使用扩展欧几里得算法求解逆元 当给定两个整数 \(a\) \(m\) 并希望找到满足条件 \( ax \equiv 1 (\text{mod}\ m)\) 的 \(x\) 值时,可以利用扩展欧几里得算法来解决这个问题。该算法不仅能够计算最大公约数 (gcd),还能找出一对整数 \(x\) \(y\) 使得 \(ax + by = gcd(a, b)\)[^1]。 对于求解模 \(m\) 下的乘法逆元而言,如果 \(gcd(a,m)=1\) 成立,则存在唯一的 \(x\) 满足上述同余关系;此时 \(x\) 即为所需求的逆元[^2]。 #### 示例题目解释 假设现在要找的是在模 \(8\) 条件下的 \(3\) 的逆元: 由于 \(gcd(3,8)=1\), 故可应用扩展欧几里得算法得到如下过程: 通过执行辗转相除法直到余数为零为止,并记录每一步的结果用于回代求解系数\(x,y\) : \[ \begin{align*} &8=3\times2+2\\ &3=2\times1+1\\ &2=1\times2+0 \\ \end{align*} \] 接着从最后一行开始向上逐步替换表达式中的被除项直至最上面一行完成整个方程式的转换工作: \[ \begin{align*} &1=3-(2\times1)\\ &=3-[8-(3\times2)]\times1\\ &=(3\times3)-(8\times1) \end{align*} \] 因此,在此情况下我们找到了一组特解 \(x_0=3,\ y_0=-1\) ,即有 \(3\times3-8\times(-1)=1\) 。所以在这个例子中,\(3\) 关于模 \(8\) 的逆元就是 \(3\) 自身[^3]。 ```cpp // C++ code to demonstrate Extended Euclidean Algorithm for finding modular inverse. #include <iostream> using namespace std; int extendedEuclid(int a, int b, int *x, int *y){ if(b==0){ *x = 1; *y = 0; return a; // returns GCD of 'a' and 'b' }else{ int r = extendedEuclid(b,a%b,x,y); int t=*x; *x=*y; *y=t-a/b**y; return r; } } void findModInverse(int A,int M){ int x,y,gcd; gcd=extendedEuclid(A,M,&x,&y); if(gcd!=1){cout<<"No solution exists";return;} cout<<(M+x%M)%M<<endl;// Ensure the result is positive } int main(){ int a=3,m=8; findModInverse(a,m); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值