1. 程式人生 > 實用技巧 >擴充套件歐幾里得演算法

擴充套件歐幾里得演算法

前置知識

斐蜀定理(貝祖定理)

寫在前面

鳴謝:擴充套件歐幾里得演算法——exgcd

Q:啥叫擴充套件歐幾里得啊

A:擴充套件歐幾里得演算法是用來在已知 \(a, b\) 求解一組 \(x, y\) ,使他們滿足斐蜀等式: \(ax + by = \gcd(a, b) = d\)

嘗試搞一下它

先考慮一下比較簡單的特殊情況,如果 \(b = 0\),那麼 \(\gcd(a, b) = a\),並顯然存在一組解 \(x = 1, y = 0\)

對於一般情況,設 \(ax + by = \gcd(a, b)\)

根據歐幾里得演算法, \(\gcd(a, b) = \gcd(b, a \bmod b)\)

肯定存在式子 \(bx_2 + (a \bmod b)y_2 = \gcd(b, a \bmod b)\)

\[\therefore ax_1 + by_1 = bx_2 + (a \!\!\mod b)y_2 \]

\[\begin{alignedat}{3} \because ax_1 + by_1 & = bx_2 + (a - a \div b \times b)y_2 \\ & = bx_2 + ay_2 - a \div b \times b \times y_2 \\ & = ay_2 + b(x_2 - a \div b \times y_2) \end{alignedat}\]

\[\therefore x_1 = y_2 , y_1 = x_2 - a \div b \times y_2 \]

繼續遞推下去就好啦~

實現程式碼:

int exgcd(int a, int b, long long &x, long long &y)
{
    if(b == 0) return x = 1, y = 0, a;
    int d = exgcd(b, a % b, y, x);//d的值實際上就是gcd(a,b),如果不需要的話可以不求
    return y -= a / b * x, d;
}

不過畢竟有擴歐這種帥氣的名字,可不能只幹這點活

它還可以求逆元

\(x\)\(a\) 在模 \(p\) 意義下的逆元,那麼滿足式子:

\[a \equiv 1 \]

那麼有:

\[ax + my = 1 \]

然後用 \(exgcd\) 搞出 \(x\) 即可(這就是為啥 \(a\)\(m\) 一定要互質才能使得 \(a\) 在模 \(m\) 意義下有逆元)

實現程式碼:

long long inv(long long a,long long m)
{
    long long x,y;
    long long d = exgcd(a, m, x, y);
    return d == 1 ? (x + m) % m : -1 ;//不互質就沒有逆元
}

\(The\) \(end.\)