深入淺出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/zh-hant/n/149405.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
KWJI的頭像KWJI
上一篇 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

發表回復

登錄後才能評論