最近一直在学习数论,讲得很快,害怕落实的不好,所以做一道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的代码其实也多不了多少

 #include <cstdio>
#include <algorithm>
#include <iostream>
#define ll long long
using namespace std;
ll a, b, x, y, k, ans;
int exgcd(ll a, ll b)
{
if(b == )
{
x = ; y = ;
return a;
}
exgcd(b,a%b);
k = x;
x = y;
y = k - a/b * y;
return x;
}
int main()
{
cin>>a>>b;
ans = exgcd(a,b);
cout<<(ans+b)%b;
return ;
}

其实你看gcd的代码这么短,肯定是背过的吧(#滑稽),exgcd也长不了多少,不行就背过吧(逃

05-22 05:17