【luogu P1082 同余方程】 题解

最近一直在学习数论,讲得很快,害怕落实的不好,所以做一道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也长不了多少,不行就背过吧(逃

 

posted @ 2018-02-26 19:25  Misaka_Azusa  阅读(195)  评论(0编辑  收藏  举报
Live2D