[数论] exgcd & 逆元

前置知识

欧几里得算法

我们首先了解一下朴素欧几里得算法(辗转相除法)。

定理:\(\gcd(a,b)=\gcd(b,a\%b)\)

简要证明

\(a=kb+r,d|a,d|b\)(即 \(d\)\(a,b\) 的任意一个公因数),且 \(a,k,b,r\) 均为正整数,\(r\ne 0\).

\(a=kb+r\)\(r=a-kb\). 且 \(a\%b=r\).

等式左右同除以 \(d\),得 \(\frac{r}{d}=\frac{a}{d}-k\frac{b}{d}\).

\(∵d|a,d|b\)

\(∴\frac{a}{d}-k\frac{b}{d}\) 为正整数.

\(\frac{r}{d}\) 为正整数.

\(∴ d|r\)

所以对于 \(\forall d\),都满足 \(d|(a\%b),d|b\),得证.

运用欧几里得算法我们可以在 \(O(\log n)\) 的时间复杂度内求出任意两数的 \(\gcd\).当然常用的 __gcd 库也运用了欧几里得算法.

__gcd 函数内容 供参考
template<typename _Mn, typename _Nn>
    constexpr common_type_t<_Mn, _Nn>
    __gcd(_Mn __m, _Nn __n)
    {
      return __m == 0 ? __detail::__abs_integral(__n)
	: __n == 0 ? __detail::__abs_integral(__m)
	: __detail::__gcd(__n, __m % __n);
    }

裴蜀定理

定理1

\(a,b\in \mathbb{Z}\),那么一定存在整数 \(x,y\) 使得 \(ax+by=\gcd(a,b)\).

证明

我们只需证明 已知 \(x',y'\) 是方程 \(bx+(a\mod b)y=d\) 时的一组特解,能够求出 \(ax+by=d\) 的解 即可.

已知

\[a\mod b = a-\lfloor\frac{a}{b}\rfloor \times b \]

显然成立.

将上式代入方程 \(bx+(a\mod b)y=d\),得:

\[bx'+ay-\lfloor\frac{a}{b}\rfloor \times by=d \]

提公因式,得:

\[ay+b(x'-\lfloor\frac{a}{b}\rfloor)=d \]

注意到上式与方程 \(bx+(a\mod b)y=d\) 是等价的,即得

\[\begin{matrix} \left\{ \begin{array}{lr} x=y', & \\ y=x'-\lfloor\frac{a}{b}\rfloor y' \end{array} \right. \end{matrix} \]

由此我们证明,若已知方程 \(bx+(a\mod b)y=d\) 的解,能够求出 \(ax+by=d\) 的解.而我们在欧几里得算法中,证明了 \(\gcd(a,b)=\gcd(b,a\%b)\),递归求解到 \(a\%b=0\) 时求解出当前方程唯一解,层层回溯即可求出方程 \(ax+by=\gcd(a,b)\) 的解.证毕.

定理2

若方程 \(ax+by=c\) 有整数解,则方程满足 \(\gcd(a,b)|c\),否则方程无整数解.

证明

\(a=p\times \gcd(a,b),b=q\times \gcd(a,b)\).

代入方程得:

\[p\times \gcd(a,b)\times x+q \times \gcd(a,b) \times y = c \]

提取公因式,得:

\(c=(px+py)·\gcd(a,b)\)

已知 \(x,y\) 为整数,得:

\(\gcd(a,b)|c\).

证毕.

定理3

\(ax+by=1\) 存在整数解,那么 \(\gcd(a,b)=1\),即 \(a,b\) 互质.

证明

同样设 \(a=p\times \gcd(a,b),b=q\times \gcd(a,b)\).

代入方程得:

\[p\times \gcd(a,b)\times x+q \times \gcd(a,b) \times y = 1 \]

方程两边同除以 \(\gcd(a,b)\),得:

\[px+qy=\frac{1}{\gcd(a,b)} \]

因此,若 \(\gcd(a,b)>1\),即 \(a,b\) 不互质,\(px+qy<1\),因为 \(p,q\) 为正整数,故方程不存在整数解.证毕.

exgcd

事实上,在裴蜀定理1中,我们的证明过程即为 exgcd 的求解过程。

exgcd 通常解决类似于这样的问题,给定 \(a,b\in\mathbb{N^*},d=\gcd(a,b)\),求方程 \(ax+by=d\) 的一组整数解.

这里给出 exgcd 的模板代码.

#include <bits/stdc++.h>
#define LL long long
using namespace std;
void exgcd(int a, int b, LL &x, LL &y)//注意 x 跟 y 是引用,因为要修改
{
    if (b == 0) {x = 1; y = 0; return ;} // gcd 算到头,准备回溯
    exgcd(b, a % b, x, y);
    LL p = x; x = y; y = p - ((LL)a / b) * y;//回溯的时候套用裴蜀定理1中推导出来的公式
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>a;
	cin>>b;
	LL x = 0, y = 0;
	exgcd(a, b, x, y); 
	cout<<x<<" "<<y<<endl;
	return 0;
}

逆元

定义 & 存在性

众所周知,形如 \(a+b,a-b,a\times b\) 式子取模,我们都可以转化成 \(a\bmod p +b\bmod p\) 形式。也就是可在任意位置进行取模而不改变运算结果。

但对于除法运算,\(\dfrac{a}{b}\bmod p \ne \dfrac{a\bmod p}{b\bmod p}\)

我们尝试找到一个数 \(b_{inv}\),使得 \(\dfrac{a}{b}\bmod p=(a\times b_{inv}\bmod p)\)。将除法转换为乘法进行运算。

定义:若满足 \(b\times b_{inv}\equiv 1(\bmod\space p)\),则称 \(b_{inv}\)\(b\)\(\bmod p\) 意义下的乘法逆元。

考虑何时乘法逆元 \(b_{inv}\) 存在。

\(b\times b_{inv}=k\times p+1\)\(g=\gcd(b,p)\)。我们转换如下。

\[g\times b_1\times b_{inv}=k\times g\times p_1+1 \]

(在上式中,\(g\times b_1=b, g\times p_1=p\)。)

简单转化得

\[g(b_1\times b_{inv}-k\times p_1=1) \]

由于我们讨论的范围是整数,故存在

\[g=1 \]

\[b_1\times b_{inv}- k\times p_1=1 \]

以上各步骤均可逆,故乘法逆元存在 当且仅当 \(\gcd(b,p)=1\)

求解

费马小定理

定理:若 \(p\) 为质数,则 \(a^{p-1}\equiv 1(\bmod\space p)\)

回顾逆元定义:\(b\times b_{inv}\equiv 1(\bmod\space p)\)

因此,若 \(p\) 为质数,则 \(b\times b^{p-2}\equiv 1(\bmod\space p)\)

只需取 \(b_{inv}=b^{p-2}\) 即可。可使用快速幂算法加速。

扩展欧几里德算法 (exgcd)

回顾:\(\text{exgcd}\) 可求解 \(ax+by=\gcd(a,b)\) 的一组 \(x,y\)

已知 \(a\times a_{inv}\equiv 1(\bmod\space p)\Leftrightarrow a\times a_{inv}+py=1\)

前文提到,逆元存在当且仅当 \(a,p\) 互质。

\[a\times a_{inv}\equiv 1(\bmod\space p)\Leftrightarrow a\times a_{inv}+py=1\Leftrightarrow a\times a_{inv}+py=\gcd(a,p) \]

应用 \(\text{exgcd}\) 求解即可。

线性求逆元

如何求解区间 \([1,n]\) 依次在 \(\bmod\space p\) 意义下的逆元?(保证 \(p\) 为质数。)

对于一个数 \(x\),满足 \(p>x\),设 \(p>kx+r,k=\lceil \dfrac{p}{x}\rceil,r=p\bmod \space x\)

\[kx+r\equiv 0(\bmod\space p) \]

我们要求 \(x_{inv}\),而 \(x\times x_{inv}\equiv 1(\bmod\space p)\)

我们首先要构造出 \(1\) 才能构造出 \(x_{inv}\)

\[kx\equiv -r(\bmod\space p) \]

左右同除以 \(r\),得

\[\dfrac{k}{r}x\equiv -1\equiv -x\times x_{inv}(\bmod\space p) \]

因此,\(\dfrac{k}{r}x\equiv -x\times x_{inv}(\bmod\space p)\),继而得

\[x_{inv}\equiv - \dfrac{k}{r}(\bmod p) \]

\(x_{inv}\equiv -k\times r_{inv}\)

因此,若我们已知 \(r_{inv}\) 的值,我们就能得到 \(x_{inv}\) 的值。

前文提到 \(r=p\bmod\space x<x\),因此在依次求 \([1,n]\) 的逆元时, \(r_{inv}\) 一定在 \(x_{inv}\) 前求出。上式即为递推式。

posted @ 2024-07-05 23:47  SXqwq  阅读(125)  评论(0编辑  收藏  举报