深入浅出exgcd

一、exgcd的概念

exgcd,全称为extended Euclidean algorithm,即扩展欧几里得算法。顾名思义,它是一种扩展版的欧几里得算法,可用于求解两个整数之间最大公约数以及对应的贝祖等式系数。通常情况下,我们只需要求解最大公约数即可满足需求,而对于贝祖等式系数,其用处比较广泛,如在密码学中用于求解模反元素等问题。

二、求解最大公约数

求解两个整数的最大公约数问题是exgcd应用最广泛的领域之一。具体做法如下:

// exgcd求解最大公约数
int exgcd(int a, int b, int &x, int &y) {
    if (b == 0) {
        x = 1;
        y = 0;
        return a;
    }
    int gcd = exgcd(b, a % b, y, x);
    y -= a / b * x;
    return gcd;
}

上述代码使用了递归的方式来求解最大公约数。需要注意的是,递归边界为$b=0$的情况,此时$x$和$y$各自为1和0,最大公约数为$a$。

三、求解贝祖等式

在exgcd求解最大公约数过程中,我们也同时求解了贝祖等式系数$x$和$y$。对于贝祖等式$a\times x+b\times y=gcd(a,b)$而言,我们可以将其视为一种线性方程,进而通过倍增、高斯消元、矩阵快速幂等方式进行求解。下面是使用倍增法的求解方式:

// a*x+b*y=gcd(a,b)的通解
pair<int, int> exgcd(int a, int b) {
    int x = 1, y = 0, lastx = 0, lasty = 1;
    while (b != 0) {
        int quotient = a / b;
        int temp = b;
        b = a % b;
        a = temp;
        temp = x;
        x = lastx - quotient * x;
        lastx = temp;
        temp = y;
        y = lasty - quotient * y;
        lasty = temp;
    }
    return make_pair(lastx, lasty);
}

当然,在实际代码编写过程中,我们可能只需要一个解即可,因此也可以进行优化,将递增过程替换为单次求解。下面是对上述代码的小改进:

// a*x+b*y=gcd(a,b)的独特解
int exgcd(int a, int b, int &x, int &y) {
    if (b == 0) {
        x = 1;
        y = 0;
        return a;
    }
    int gcd = exgcd(b, a % b, y, x);
    y -= a / b * x;
    return gcd;
}
// 求解a*x+b*y=gcd(a,b)的解x
int exgcd(int a, int b, int gcd) {
    int x, y;
    exgcd(a, b, x, y);
    return (x % (b / gcd) + b / gcd) % (b / gcd);
}

四、应用举例

在具体应用中,exgcd的用处比较广泛,如以下几个场景:

情景1: 判断两个整数是否互质。

当两个整数互质时,其最大公约数为1。因此我们只需要判断exgcd返回的最大公约数是否为1即可。下面是相应的代码实现:

// 判断两个整数是否互质
bool is_coprime(int a, int b) {
    return exgcd(a, b) == 1;
}

情景2: 解决同余方程组。

同余方程组是以模同余关系为基础的方程组。通常我们可以通过中国剩余定理进行求解,而exgcd则是其最基础的组成部分。以例1为例:

例1: 求解同余方程组

$x\equiv 2(mod\;3)$

$x\equiv 3(mod\;5)$

通常情况下,我们可以使用中国剩余定理得到通解,但此处我们先使用exgcd求解该方程组:

pair<int, int> exgcd(int a, int b) {
    int x = 1, y = 0, lastx = 0, lasty = 1;
    while (b != 0) {
        int quotient = a / b;
        int temp = b;
        b = a % b;
        a = temp;
        temp = x;
        x = lastx - quotient * x;
        lastx = temp;
        temp = y;
        y = lasty - quotient * y;
        lasty = temp;
    }
    return make_pair(lastx, lasty);
}
// 求解同余方程组x=a1(mod m1),x=a2(mod m2)的通解,时间复杂度O(log(m1+m2))
int exCRT(int a1, int m1, int a2, int m2) {
    int gcd = exgcd(m1, m2).first;
    int x = ((a2 - a1) % m2 + m2) % m2 * exgcd(m1 / gcd, m2 / gcd).first % (m2 / gcd) * m1 % m2 + a1;
    return gcd == 1 ? x : -1;
}

上述代码实现了exgcd在求解同余方程组中的应用,时间复杂度为$O(log(m1+m2))$。

总结

exgcd是解决数学问题的一种基础工具,其应用范围比较广泛,通常用于求解最大公约数、贝祖等式、判断两个整数是否互质、解决同余方程组等问题。同样重要的是,掌握exgcd的理论知识,可以帮助我们更加深入理解相关算法、降低算法实现难度。本文从多个角度对exgcd做了详细的阐述,并提供了相应的代码实现,希望能够帮助读者更好地掌握这一重要的算法。

原创文章,作者:KWJI,如若转载,请注明出处:https://www.506064.com/n/149405.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
KWJIKWJI
上一篇 2024-11-04 17:51
下一篇 2024-11-04 17:51

相关推荐

  • 深入浅出统计学

    统计学是一门关于收集、分析、解释和呈现数据的学科。它在各行各业都有广泛应用,包括社会科学、医学、自然科学、商业、经济学、政治学等等。深入浅出统计学是指想要学习统计学的人能够理解统计…

    编程 2025-04-25
  • 深入浅出torch.autograd

    一、介绍autograd torch.autograd 模块是 PyTorch 中的自动微分引擎。它支持任意数量的计算图,可以自动执行前向传递、后向传递和计算梯度,同时提供很多有用…

    编程 2025-04-24
  • 深入浅出SQL占位符

    一、什么是SQL占位符 SQL占位符是一种占用SQL语句中某些值的标记或占位符。当执行SQL时,将使用该标记替换为实际的值,并将这些值传递给查询。SQL占位符使查询更加安全,防止S…

    编程 2025-04-24
  • 深入浅出:理解nginx unknown directive

    一、概述 nginx是目前使用非常广泛的Web服务器之一,它可以运行在Linux、Windows等不同的操作系统平台上,支持高并发、高扩展性等特性。然而,在使用nginx时,有时候…

    编程 2025-04-24
  • 深入浅出ThinkPHP框架

    一、简介 ThinkPHP是一款开源的PHP框架,它遵循Apache2开源协议发布。ThinkPHP具有快速的开发速度、简便的使用方式、良好的扩展性和丰富的功能特性。它的核心思想是…

    编程 2025-04-24
  • 深入浅出arthas火焰图

    arthas是一个非常方便的Java诊断工具,包括很多功能,例如JVM诊断、应用诊断、Spring应用诊断等。arthas使诊断问题变得更加容易和准确,因此被广泛地使用。artha…

    编程 2025-04-24
  • 深入浅出AWK -v参数

    一、功能介绍 AWK是一种强大的文本处理工具,它可以用于数据分析、报告生成、日志分析等多个领域。其中,-v参数是AWK中一个非常有用的参数,它用于定义一个变量并赋值。下面让我们详细…

    编程 2025-04-24
  • 深入浅出Markdown文字颜色

    一、Markdown文字颜色的背景 Markdown是一种轻量级标记语言,由于其简单易学、易读易写,被广泛应用于博客、文档、代码注释等场景。Markdown支持使用HTML标签,因…

    编程 2025-04-23
  • 深入浅出runafter——异步任务调度器的实现

    一、runafter是什么? runafter是一个基于JavaScript实现的异步任务调度器,可以帮助开发人员高效地管理异步任务。利用runafter,开发人员可以轻松地定义和…

    编程 2025-04-23
  • 深入浅出TermQuery

    一、TermQuery概述 TermQuery是Lucene中最基本、最简单、最常见的查询方法之一。它完全符合其名字,意味着只能对一个单词进行查询。 TermQuery可以用于搜索…

    编程 2025-04-23

发表回复

登录后才能评论