1. 程式人生 > >【luogu P1082 同余方程】題解

【luogu P1082 同余方程】題解

ont 當前 int 關於 學習 並且 div iostream color

最近一直在學習數論,講得很快,害怕落實的不好,所以做一道luogu的同余方程練練手。

關於x的同余方程

ax ≡ 1 mod m

那麽x其實就是求a關於m的乘法逆元

ax + my = 1

對於這個不定方程的全部解是

{ x = x0 + m/gcd(a,m)

{ y = y0 - a/gcd(a,m)

我們可以用exgcd來求出其中的一組特解x0

那麽什麽是exgcd?

先不考慮exgcd,假設當前我們要處理的是求出 a 和 b的最大公約數,並求出 x 和 y 使得 a*x + b*y= gcd ,而我們已經求出了下一個狀態:b 和 a%b 的最大公約數,並且求出了一組x1 和y1 使

得: b*x1 + (a%b)*y1 = gcd

那麽我們看 a%b = (a-(a/b)*b)

所以
gcd = b*x1 + (a%b)*y1
= b*x1 + (a-(a/b)*b)*y1
= b*x1 + a*y1 – (a/b)*b*y1
= a*y1 + b*(x1 – a/b*y1)

那麽我們對比前面一組 a*x + b*y = gcd

在這裏 x = y1

y = x1 - a/b*y1

所以我們就可以遞歸來求exgcd了。

在gcd當中,gcd(a,b) = gcd(b,a%b)

那麽exgcd的代碼其實也多不了多少

 1 #include <cstdio>
 2 #include <algorithm>
 3
#include <iostream> 4 #define ll long long 5 using namespace std; 6 ll a, b, x, y, k, ans; 7 int exgcd(ll a, ll b) 8 { 9 if(b == 0) 10 { 11 x = 1; y = 0; 12 return a; 13 } 14 exgcd(b,a%b); 15 k = x; 16 x = y; 17 y = k - a/b * y; 18 return x;
19 } 20 int main() 21 { 22 cin>>a>>b; 23 ans = exgcd(a,b); 24 cout<<(ans+b)%b; 25 return 0; 26 }

其實你看gcd的代碼這麽短,肯定是背過的吧(#滑稽),exgcd也長不了多少,不行就背過吧(逃

【luogu P1082 同余方程】題解