ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

扩展欧几里得算法

2022-01-27 21:04:26  阅读:177  来源: 互联网

标签:return 欧几里得 扩展 exgcd 算法 ax LL


文章目录


扩展欧几里得算法

裴蜀定理

在这里插入图片描述

ax + by能够凑出来的最小的值一定是a和b的最大公约数(d的一倍)。

应用:扩展欧几里得算法求系数xy

欧几里得算法

【代码模板】

LL gcd(LL a, LL b)
{
	if(b == 0) return a;
	return gcd(b, a % b);
}

扩展欧几里得算法证明与实现

设LL exgcd(a,b,x,y)是求解系数x,y的函数,返回值是gcd(a,b),那么可以根据递归求出exacd(b,a%b,i,j)求出系数i,j

根据下面的推导得到x,y与i,j的关系:

在这里插入图片描述

【代码模板】

LL exgcd(LL a, LL b, LL &x, LL &y)// 通过引用传回
{
    if(b == 0)
    {
        x = 1, y = 0;
        return a;
    }
    LL d = exgcd(b, a % b, y, x);// 注意:这里换一下顺序y
    y -= a / b * x; // x = x1
    return d;
}

【题目链接】877. 扩展欧几里得算法 - AcWing题库

在这里插入图片描述

【代码实现】

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long LL;

LL exgcd(LL a, LL b, LL &x, LL &y)
{
    if(b == 0)
    {
        x = 1, y = 0;
        return a;
    }
    LL d = exgcd(b, a % b, y, x);// 注意:这里换一下顺序y
    y -= a / b * x; // x = x1
    return d;
}

int main()
{
    int n;
    scanf("%d", &n);
    
    while (n -- )
    {
        LL a, b, x, y;
        scanf("%lld%lld", &a, &b);
        
        exgcd(a, b, x, y);
        printf("%lld %lld\n", x, y);
    }
    
    return 0;
}

线性同余方程

【题目链接】878. 线性同余方程 - AcWing题库

a * x ≡ b (mod m)

----> ax = my + b(y为m的整数倍)

----> ax - my = b,令y1 = -y ----> ax + my1 = b

根据拓展欧几里得定理,只要 b a与m最大公约数的倍数,即b为gcd(a, m)的倍数即有解!反之无解。

若b是最大公约数的倍数,由拓展欧几里得算法可以求出一个系数x:X1使得ax + my1 = dd为a与m的最大公约数

在有解情况下,由于d与b存在倍数关系,我们可以将ax + my1 = d两边同时扩大b/d倍,由于a与m都是定数,也就是说ax + my1 = b中的x也就是我们题目要求的x会在 上述拓展欧几里得算法求出一个系数x:X1的基础上乘上b/d倍。
// 即最后答案为:x= X1 * d / b % m

ax % m=b⟺ a⋅(x % m) % m=b

​ 所以对x % m仍是个答案
因为输出要在int范围,所以%m

【代码实现】

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;
typedef long long LL;

LL exgcd(LL a, LL 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;
}

// ax % m == b -- > ax = my + b ---> ax + my1 = b
int main()
{
    int n;
    scanf("%d", &n);
    
    while (n -- )
    {
        LL a, b, m, x, y;
        scanf("%lld%lld%lld", &a, &b, &m);
        
        LL d = exgcd(a, m, x, y);
        if(b % d) puts("impossible");//b 不是 d的倍数 则无解
        else printf("%lld\n",  LL(b/d) * x % m);
    }
    
    return 0;
}

学习内容参考:
acwing算法基础课

标签:return,欧几里得,扩展,exgcd,算法,ax,LL
来源: https://blog.csdn.net/qq_54773252/article/details/122723399

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有