线性同余与乘法逆元
欧几里得算法
∀
a
,
b
∈
N
,
gcd
(
a
,
b
)
=
gcd
(
b
,
a
m
o
d
b
)
\forall a,b\in \N,\gcd(a,b)=\gcd(b,a\bmod b)
∀a,b∈N,gcd(a,b)=gcd(b,amodb)
证明:
考
虑
记
a
与
b
的
公
因
数
为
d
∵
∃
t
,
k
,
r
∈
N
,
b
=
t
⋅
d
,
a
=
k
⋅
(
t
⋅
d
)
+
r
∵
d
∣
b
,
d
∣
a
∴
∃
x
∈
N
,
x
⋅
d
=
a
=
k
⋅
(
t
⋅
d
)
+
r
⇔
x
=
k
⋅
(
t
⋅
d
)
+
r
d
=
k
t
+
r
d
∵
x
∈
N
∴
d
∣
r
∴
d
∣
(
a
m
o
d
b
)
∴
a
m
o
d
b
的
因
数
集
与
a
与
b
的
公
因
数
集
相
同
∴
gcd
(
a
,
b
)
=
gcd
(
b
,
b
m
o
d
a
)
考虑记a与b的公因数为d\\\because \exist t,k,r\in\N,b=t\cdot d,a=k\cdot (t \cdot d)+r\\\because d\mid b,d\mid a\\\therefore \exist x\in\N,x\cdot d=a=k⋅(t⋅d)+r\\\quad \Leftrightarrow x=\dfrac{k⋅(t⋅d)+r}{d}=kt+\dfrac{r}{d}\\\because x\in \N\\\therefore d\mid r\\\therefore d\mid (a\bmod b)\\\therefore a\bmod b 的因数集与a与b的公因数集相同\\\therefore \gcd(a,b)=\gcd(b,b\bmod a)
考虑记a与b的公因数为d∵∃t,k,r∈N,b=t⋅d,a=k⋅(t⋅d)+r∵d∣b,d∣a∴∃x∈N,x⋅d=a=k⋅(t⋅d)+r⇔x=dk⋅(t⋅d)+r=kt+dr∵x∈N∴d∣r∴d∣(amodb)∴amodb的因数集与a与b的公因数集相同∴gcd(a,b)=gcd(b,bmoda)
此算法也常称为辗转相除法。
#include<bits/stdc++.h>
using namespace std;
int a,b;
int gcd(int x,int y)
{
if(y==0) return x;
int r=x%y;
return gcd(y,r);
}
int main()
{
cin>>a>>b;
cout<<gcd(a,b);
return 0;
}
裴蜀定理
对
于
a
,
b
∈
N
,
x
,
y
∈
Z
,
则
关
于
x
,
y
的
不
定
方
程
有
对于a,b\in \N,x,y\in\Z,则关于x,y的不定方程有
对于a,b∈N,x,y∈Z,则关于x,y的不定方程有
a
x
+
b
y
=
gcd
(
a
,
b
)
ax+by=\gcd(a,b)
ax+by=gcd(a,b)
证明:
先
考
虑
证
明
a
x
+
b
y
的
和
为
gcd
(
a
,
b
)
倍
数
∵
∃
x
′
,
y
′
∈
N
,
a
=
x
′
⋅
gcd
(
a
,
b
)
,
b
=
y
′
⋅
gcd
(
a
,
b
)
∴
a
x
+
b
y
=
x
⋅
x
′
gcd
(
a
,
b
)
+
y
⋅
y
′
gcd
(
a
,
b
)
=
gcd
(
a
,
b
)
⋅
(
x
x
′
+
y
y
′
)
∴
gcd
(
a
,
b
)
∣
(
a
x
+
b
y
)
∴
∀
t
∈
Z
,
a
x
+
b
y
=
t
⋅
gcd
(
a
,
b
)
先考虑证明~ax+by 的和为\gcd(a,b)倍数\\\because \exist x',y'\in\N,a=x'\cdot\gcd(a,b),b=y'\cdot\gcd(a,b)\\\therefore ax+by=x\cdot x'\gcd(a,b)+y\cdot y'\gcd(a,b)\\\qquad\qquad\,\,\,=\gcd(a,b)\cdot(xx'+yy')\\\therefore \gcd(a,b)\mid (ax+by)\\\therefore \forall t\in\Z,ax+by=t\cdot \gcd(a,b)
先考虑证明 ax+by的和为gcd(a,b)倍数∵∃x′,y′∈N,a=x′⋅gcd(a,b),b=y′⋅gcd(a,b)∴ax+by=x⋅x′gcd(a,b)+y⋅y′gcd(a,b)=gcd(a,b)⋅(xx′+yy′)∴gcd(a,b)∣(ax+by)∴∀t∈Z,ax+by=t⋅gcd(a,b)
显然只有当等式右边为 gcd ( a , b ) \gcd(a,b) gcd(a,b)或 gcd ( a , b ) \gcd(a,b) gcd(a,b)倍数时才存在整数解。
扩展欧几里得算法
我们再来考虑如何找到这个不定方程的一个特解。
考 虑 当 b = 0 时 , 显 然 有 一 对 ( x , y ) , 使 得 ( x , y ) = ( 1 , 0 ) 时 满 足 要 求 , 即 a + 0 = gcd ( a , 0 ) 考 虑 当 b ≠ 0 时 , 根 据 欧 几 里 得 算 法 , 有 gcd ( a , b ) = gcd ( b , a m o d b ) ∴ ∃ x ′ , y ′ ∈ Z , a x + b y = b x ′ + ( a m o d b ) y ′ = b x ′ + ( a − ⌊ a b ⌋ ⋅ b ) y ′ = b x ′ + a y ′ − ⌊ a b ⌋ b y ′ = a y ′ + b ( x ′ − ⌊ a b ⌋ y ′ ) x = y ′ y = x ′ − ⌊ a b ⌋ y ′ 考虑当 b=0时,显然有一对(x,y),使得(x,y)=(1,0)时满足要求,即a+0=\gcd(a,0)\\考虑当b\ne 0时,根据欧几里得算法,有 \gcd(a,b)=\gcd(b,a\bmod b)\\\therefore \exist x',y'\in \Z,\, ax+by=bx'+(a\bmod b)y'\\ \,\,\,\,=bx'+(a-\left\lfloor\dfrac{a}{b}\right\rfloor \cdot b)y'\\ \,\,\,\,=bx'+ay'-\left\lfloor\dfrac{a}{b}\right\rfloor by'\\\,\,\,\,=ay'+b(x'-\left\lfloor \dfrac{a}{b}\right\rfloor y')\\x=y'\\\quad y=x'-\left\lfloor\dfrac{a}{b}\right\rfloor y' 考虑当b=0时,显然有一对(x,y),使得(x,y)=(1,0)时满足要求,即a+0=gcd(a,0)考虑当b=0时,根据欧几里得算法,有gcd(a,b)=gcd(b,amodb)∴∃x′,y′∈Z,ax+by=bx′+(amodb)y′=bx′+(a−⌊ba⌋⋅b)y′=bx′+ay′−⌊ba⌋by′=ay′+b(x′−⌊ba⌋y′)x=y′y=x′−⌊ba⌋y′
因此,只需求出 x ′ , y ′ x',y' x′,y′就可以得到 x , y x,y x,y,而 x ′ , y ′ x',y' x′,y′可以由方程右边为 gcd ( b , a m o d b ) \gcd(b,a\bmod b) gcd(b,amodb) 时得到,这不就是一个欧几里得算法的递归过程吗?我们往上层层递归,直到当b为0时我们就可以得到 ( x , y ) = ( 1 , 0 ) (x,y)=(1,0) (x,y)=(1,0),然后我们就可以运用上述公式递归求得 ( x , y ) (x,y) (x,y)
解决这种不定方程的问题常在欧几里得算法中实现,因此被称为扩展欧几里得算法,也称为 e x g c d exgcd exgcd。
#include <bits/stdc++.h>
using namespace std;
int a,b;
int x,y;
int exgcd(int l,int r)
{
if(r==0)
{
x=1;
y=0;
return l;
}
int d=exgcd(r,l%r);
int t=x;
x=y;
y=t-l/r*y;
return d;
}
int main()
{
cin>>a>>b;
int ans=exgcd(a,b);
cout<<x<<" "<<y<<" "<<ans;
return 0;
}
继续观察这个不定方程,此时我们已经可以用上述算法找到一个特解 ( x 0 , y 0 ) (x_0,y_0) (x0,y0),我们现在来思考如何得到这个不定方程的通解。
我 们 考 虑 从 方 程 的 特 解 入 手 , 现 在 我 们 已 经 拥 有 了 两 个 不 定 方 程 : 1. a x + b y = gcd ( a , b ) 2. a x 0 + b y 0 = gcd ( a , b ) 由 1 式 减 去 2 式 得 : a ( x − x 0 ) + b ( y − y 0 ) = 0 ⇔ a ( x − x 0 ) = b ( y 0 − y ) 考 虑 等 式 两 边 同 时 除 以 gcd ( a , b ) a gcd ( a , b ) ( x − x 0 ) = b gcd ( a , b ) ( y 0 − y ) 显 然 有 a gcd ( a , b ) 与 b gcd ( a , b ) 互 质 ∴ ∀ t ∈ Z , x − x 0 = t ⋅ b gcd ( a , b ) , y 0 − y = t ⋅ a gcd ( a , b ) ∴ x = x 0 + t ⋅ b gcd ( a , b ) y = y 0 − t ⋅ a gcd ( a , b ) 我们考虑从方程的特解入手,现在我们已经拥有了两个不定方程:\\\mathbb{1.}ax+by=\gcd(a,b)\\\mathbb{2.}ax_0+by_0=\gcd(a,b)\\由~\mathbb{1}~式减去~\mathbb{2}~式得:~a(x-x_0)+b(y-y_0)=0\\\Leftrightarrow a(x-x_0)=b(y_0-y)\\考虑等式两边同时除以\gcd(a,b)\\~\\\dfrac{a}{\gcd(a,b)}(x-x_0)=\dfrac{b}{\gcd(a,b)}(y_0-y)\\~\\显然有\dfrac{a}{\gcd(a,b)}与\dfrac{b}{\gcd(a,b)}互质\\~\\\therefore \forall t\in\Z,x-x_0=t\cdot \dfrac{b}{\gcd(a,b)},y_0-y=t\cdot \dfrac{a}{\gcd(a,b)}\\~\\\therefore x=x_0+t\cdot \dfrac{b}{\gcd(a,b)}\\\quad y=y_0-t\cdot\dfrac{a}{\gcd(a,b)} 我们考虑从方程的特解入手,现在我们已经拥有了两个不定方程:1.ax+by=gcd(a,b)2.ax0+by0=gcd(a,b)由 1 式减去 2 式得: a(x−x0)+b(y−y0)=0⇔a(x−x0)=b(y0−y)考虑等式两边同时除以gcd(a,b) gcd(a,b)a(x−x0)=gcd(a,b)b(y0−y) 显然有gcd(a,b)a与gcd(a,b)b互质 ∴∀t∈Z,x−x0=t⋅gcd(a,b)b,y0−y=t⋅gcd(a,b)a ∴x=x0+t⋅gcd(a,b)by=y0−t⋅gcd(a,b)a
于是我们就得到了由不定方程特解得到通解的方法。
接下来我们再来扩展一下,考虑如何求出不定方程中 x x x 的最小非负整数解。
考 虑 到 我 们 是 从 x = x 0 + t ⋅ b gcd ( a , b ) 得 到 所 有 的 x 的 , 因 此 , 想 要 求 最 小 的 非 负 整 数 x , 实 际 上 是 要 满 足 以 下 式 子 x 0 + t ⋅ b gcd ( a , b ) ≥ 0 , x 0 + ( t + 1 ) ⋅ b gcd ( a , b ) ≤ 0 由 于 t 可 取 任 意 整 数 , 因 此 上 述 式 子 等 价 于 x 0 − t ⋅ b gcd ( a , b ) ≥ 0 , x 0 − ( t + 1 ) ⋅ b gcd ( a , b ) ≤ 0 很 显 然 , 此 时 最 小 的 x 非 负 整 数 值 可 以 由 x 0 m o d b gcd ( a , b ) 得 到 但 考 虑 到 x 0 有 可 能 是 负 数 , 此 时 我 们 应 该 考 虑 如 何 将 负 数 取 模 转 换 为 正 数 取 模 对 于 负 数 x m o d m 的 值 , 考 虑 m o d 的 性 质 , 这 个 式 子 等 价 于 ( ( x m o d m ) + m ) m o d m 因 此 我 们 考 虑 对 ( x 0 m o d b gcd ( a , b ) ) + b gcd ( a , b ) 来 确 保 式 子 永 远 为 正 数 , 后 在 对 其 取 m o d 因 此 , x 的 最 小 非 负 整 数 解 为 ( ( x 0 m o d b gcd ( a , b ) ) + b gcd ( a , b ) ) m o d b gcd ( a , b ) 考虑到我们是从 x=x_0+t\cdot\dfrac{b}{\gcd(a,b)} 得到所有的x的,因此,想要求最小的非负整数x,实际上是要满足以下式子\\~\\x_0+t\cdot\dfrac{b}{\gcd(a,b)}\ge0,x_0+(t+1)\cdot\dfrac{b}{\gcd(a,b)}\le 0\\由于t可取任意整数,因此上述式子等价于\\x_0-t\cdot\dfrac{b}{\gcd(a,b)}\ge0,x_0-(t+1)\cdot\dfrac{b}{\gcd(a,b)}\le 0\\~\\很显然,此时最小的x非负整数值可以由x_0\bmod \dfrac{b}{\gcd(a,b)}得到\\但考虑到x_0有可能是负数,此时我们应该考虑如何将负数取模转换为正数取模\\~\\对于负数x\bmod m的值,考虑\bmod 的性质,这个式子等价于((x\bmod m)+m)\bmod m\\~\\因此我们考虑对(x_0\bmod \dfrac{b}{\gcd(a,b)})+\dfrac{b}{\gcd(a,b)}来确保式子永远为正数,后在对其取\bmod\\~\\因此,x的最小非负整数解为 ((x_0\bmod \dfrac{b}{\gcd(a,b)})+\dfrac{b}{\gcd(a,b)})\bmod \dfrac{b}{\gcd(a,b)} 考虑到我们是从x=x0+t⋅gcd(a,b)b得到所有的x的,因此,想要求最小的非负整数x,实际上是要满足以下式子 x0+t⋅gcd(a,b)b≥0,x0+(t+1)⋅gcd(a,b)b≤0由于t可取任意整数,因此上述式子等价于x0−t⋅gcd(a,b)b≥0,x0−(t+1)⋅gcd(a,b)b≤0 很显然,此时最小的x非负整数值可以由x0modgcd(a,b)b得到但考虑到x0有可能是负数,此时我们应该考虑如何将负数取模转换为正数取模 对于负数xmodm的值,考虑mod的性质,这个式子等价于((xmodm)+m)modm 因此我们考虑对(x0modgcd(a,b)b)+gcd(a,b)b来确保式子永远为正数,后在对其取mod 因此,x的最小非负整数解为((x0modgcd(a,b)b)+gcd(a,b)b)modgcd(a,b)b
例题
https://www.luogu.com.cn/problem/P1516
线性同余方程
给定正数
a
,
b
,
m
a,b,m
a,b,m,求一个整数
x
x
x满足
a
⋅
x
≡
n
(
m
o
d
b
)
a\cdot x\equiv n\pmod b
a⋅x≡n(modb),或者无解。
由于未知数是一次的,因此我们称
a
x
≡
n
(
m
o
d
b
)
ax\equiv n\pmod b
ax≡n(modb) 为线性同余方程(一次同余方程)。
我 们 考 虑 同 余 方 程 a x ≡ n ( m o d b ) , 则 定 有 b ∣ ( a x − n ) 因 此 有 y ∈ Z , 使 得 a x − n = b y , 即 a x − b y = n , 由 于 y 可 取 任 意 整 数 , 因 此 等 价 于 a x + b y = n 我们考虑同余方程 ax\equiv n\pmod b,则定有b\mid(ax-n)\\因此有y\in\Z,使得ax-n=by,即ax-by=n,由于y可取任意整数,因此等价于 ax+by=n 我们考虑同余方程ax≡n(modb),则定有b∣(ax−n)因此有y∈Z,使得ax−n=by,即ax−by=n,由于y可取任意整数,因此等价于ax+by=n
于是我们就将同余方程转换为了一个不定方程,此方程当且仅当
gcd
(
a
,
b
)
∣
n
\gcd(a,b)\mid n
gcd(a,b)∣n 时存在整数解。
当存在整数解时,我们可以通过扩展欧几里得算法求出不定方程
a
x
+
b
y
=
gcd
(
a
,
b
)
ax+by=\gcd(a,b)
ax+by=gcd(a,b)时的一个特解
(
x
0
,
y
0
)
(x_0,y_0)
(x0,y0)。
由于
n
=
n
gcd
(
a
,
b
)
⋅
gcd
(
a
,
b
)
,
n=\dfrac{n}{\gcd(a,b)}\cdot \gcd(a,b),
n=gcd(a,b)n⋅gcd(a,b),因此不定方程
a
x
+
b
y
=
n
ax+by=n
ax+by=n的特解即为
(
x
0
⋅
n
gcd
(
a
,
b
)
,
y
0
⋅
n
gcd
(
a
,
b
)
)
(x_0\cdot \dfrac{n}{\gcd(a,b)},y_0\cdot \dfrac{n}{\gcd(a,b)})
(x0⋅gcd(a,b)n,y0⋅gcd(a,b)n)
转换可得线性同余方程
a
x
≡
n
(
m
o
d
b
)
ax\equiv n\pmod b
ax≡n(modb) 的一个特解
x
0
⋅
n
gcd
(
a
,
b
)
x_0\cdot \dfrac{n}{\gcd(a,b)}
x0⋅gcd(a,b)n。
一个定理:
对 于 一 个 线 性 同 余 方 程 a x ≡ n ( m o d b ) 对于一个线性同余方程ax\equiv n\pmod b 对于一个线性同余方程ax≡n(modb),都有 gcd ( a , b ) 个 m o d b 不 同 余 的 解 , 若 已 知 第 一 个 解 为 x 0 , 则 x i = x 0 + i ⋅ b gcd ( a , b ) , i ∈ Z , 0 ≤ i < gcd ( a , b ) 。 \gcd(a,b)个\bmod b不同余的解,若已知第一个解为x_0,则x_i=x_0+i\cdot \dfrac{b}{\gcd(a,b)},i\in\Z,0\le i<\gcd(a,b)。 gcd(a,b)个modb不同余的解,若已知第一个解为x0,则xi=x0+i⋅gcd(a,b)b,i∈Z,0≤i<gcd(a,b)。
证明:
考
虑
证
明
x
i
=
x
0
+
i
⋅
b
gcd
(
a
,
b
)
是
方
程
的
解
:
∵
a
x
i
≡
n
(
m
o
d
b
)
⇔
a
(
x
0
+
i
⋅
b
gcd
(
a
,
b
)
)
≡
n
(
m
o
d
b
)
⇔
a
x
0
+
a
⋅
i
⋅
b
gcd
(
a
,
b
)
≡
n
(
m
o
d
b
)
⇔
a
x
0
+
i
⋅
lcm
(
a
,
b
)
≡
n
(
m
o
d
b
)
∵
i
⋅
lcm
(
a
,
b
)
m
o
d
b
=
0
∴
a
x
0
+
i
⋅
lcm
(
a
,
b
)
≡
a
x
0
(
m
o
d
b
)
∴
a
x
i
≡
a
x
0
≡
n
(
m
o
d
b
)
因
此
x
i
=
x
0
+
i
⋅
b
gcd
(
a
,
b
)
是
方
程
的
解
∵
0
≤
i
<
gcd
(
a
,
b
)
∴
0
≤
i
⋅
b
gcd
(
a
,
b
)
<
b
∴
x
0
⋯
i
显
然
m
o
d
b
互
不
同
余
,
且
有
gcd
(
a
,
b
)
个
解
考虑证明x_i=x_0+i\cdot \dfrac{b}{\gcd(a,b)}是方程的解:\\\because ax_i\equiv n\pmod b\\\Leftrightarrow a(x_0+i\cdot \dfrac{b}{\gcd(a,b)})\equiv n\pmod b\\\Leftrightarrow ax_0+a\cdot i\cdot \dfrac{b}{\gcd(a,b)}\equiv n\pmod b\\\Leftrightarrow ax_0+i\cdot \operatorname{lcm}(a,b)\equiv n\pmod b\\\because i\cdot \operatorname{lcm}(a,b)\bmod b=0\\\therefore ax_0+i\cdot \operatorname{lcm}(a,b)\equiv ax_0\pmod b\\\therefore ax_i\equiv ax_0\equiv n\pmod b\\因此x_i=x_0+i\cdot \dfrac{b}{\gcd(a,b)}是方程的解\\~\\\because0\le i<\gcd(a,b)\\\therefore 0\le i\cdot \dfrac{b}{\gcd(a,b)}<b\\\therefore x_{0\cdots i}显然\bmod b互不同余,且有\gcd(a,b)个解
考虑证明xi=x0+i⋅gcd(a,b)b是方程的解:∵axi≡n(modb)⇔a(x0+i⋅gcd(a,b)b)≡n(modb)⇔ax0+a⋅i⋅gcd(a,b)b≡n(modb)⇔ax0+i⋅lcm(a,b)≡n(modb)∵i⋅lcm(a,b)modb=0∴ax0+i⋅lcm(a,b)≡ax0(modb)∴axi≡ax0≡n(modb)因此xi=x0+i⋅gcd(a,b)b是方程的解 ∵0≤i<gcd(a,b)∴0≤i⋅gcd(a,b)b<b∴x0⋯i显然modb互不同余,且有gcd(a,b)个解
#include<bits/stdc++.h>
using namespace std;
int a,n,b;
int x,y;
int exgcd(int l,int r)
{
if(r==0)
{
x=1;
y=0;
return l;
}
int d=exgcd(r,l%r);
int t=x;
x=y;
y=t-l/r*y;
return d;
}
void mod_slover()
{
int g=exgcd(a,b);
if(n%g!=0) exit(0);//判断是否有解
x=(x*(n/g))%b;
x=x*(n/g); //求解
x=((x%(b/g))+(b/g))%(b/g); //取得最小正整数解
for(int i=0;i<g;i++)
{
cout<<x+i*(b/g)<<endl;
}
//枚举g个不同余的解
}
int main()
{
cin>>a>>n>>b;
mod_slover();
return 0;
}
例题
https://www.luogu.com.cn/problem/P1082
https://www.luogu.com.cn/problem/P5656
乘法逆元
或许乘法逆元有一个更加感性的理解:同余方程余数意义下的倒数
考 虑 a , b , m ∈ Z , gcd ( b , m ) = 1 , 若 存 在 x ∈ Z , 且 满 足 a b ≡ a x ( m o d m ) , 则 称 x 为 b 的 乘 法 逆 元 若 a b ≡ a x ( m o d m ) , 则 有 a ≡ a b x ( m o d m ) ⇔ b x ≡ 1 ( m o d m ) , 因 此 这 也 是 乘 法 逆 元 的 一 种 定 义 。 考虑a,b,m\in\Z,\gcd(b,m)=1,若存在x\in\Z,且满足\dfrac{a}{b}\equiv ax\pmod m,则称x为b的\color{Blue}乘法逆元\\~\\\color{Black}若\dfrac{a}{b}\equiv ax\pmod m,则有a\equiv abx\pmod m\Leftrightarrow \color{Blue}bx\equiv 1\pmod m,\color{Black}因此这也是乘法逆元的一种定义。 考虑a,b,m∈Z,gcd(b,m)=1,若存在x∈Z,且满足ba≡ax(modm),则称x为b的乘法逆元 若ba≡ax(modm),则有a≡abx(modm)⇔bx≡1(modm),因此这也是乘法逆元的一种定义。
因此我们就可以通过解 b x ≡ 1 ( m o d m ) bx\equiv 1\pmod m bx≡1(modm)这个线性同余方程,得到最小正数解 x x x,便得到 b b b的乘法逆元。
知道了这么个名字就很酷的东西有什么用呢?观察乘法逆元的第一个定义,有了它我们就可以处理有理数取余(特别是当 a , b a,b a,b特别大的情况下,同余性质很重要)。
不想贴了,就是求线性同余方程的解
利用 b b b在 m o d m \bmod m modm意义下的乘法逆元 b − 1 b^{-1} b−1,我们可以得到 a b m o d m \dfrac{a}{b}\bmod m bamodm的值,即为 a b − 1 m o d m ab^{-1}\bmod m ab−1modm
例题
https://www.luogu.com.cn/problem/P2613
线性求逆元
考虑给出 p p p,若要求 [ 1 , p ] [1,p] [1,p]内所有数在 m o d p \bmod~p mod p意义下的乘法逆元,是否具有复杂度优的递推公式呢?
考 虑 求 i 的 乘 法 逆 元 , 则 有 ∃ k , r ∈ Z , p = k ⋅ i + r , 显 然 k ⋅ i + r ≡ 0 ( m o d p ) 将 同 余 方 程 两 边 同 时 乘 以 i 的 逆 元 i − 1 k ⋅ ( i ⋅ i − 1 ) + r ⋅ i − 1 ≡ 0 ( m o d p ) k + r ⋅ i − 1 ≡ 0 ( m o d p ) 移 项 得 r ⋅ i − 1 ≡ − k ( m o d p ) 再 尝 试 将 r 消 掉 , 于 是 乘 以 r − 1 i − 1 ≡ − k ⋅ r − 1 ( m o d p ) 考 虑 k = ⌊ p i ⌋ , r = p m o d i , 带 入 i − 1 ≡ − ⌊ p i ⌋ ⋅ ( p m o d i ) − 1 ( m o d p ) 考 虑 − ⌊ p i ⌋ m o d p 可 以 转 换 为 p − ⌊ p i ⌋ i − 1 ≡ ( p − ⌊ p i ⌋ ) ( p m o d i ) − 1 ( m o d p ) 考虑求i的乘法逆元,则有\exist k,r\in \Z,p=k\cdot i+r,显然\\k\cdot i+r\equiv 0\pmod p\\将同余方程两边同时乘以 i 的逆元 i^{-1}\\k\cdot (i\cdot i^{-1})+r\cdot i^{-1}\equiv 0\pmod p\\k+r\cdot i^{-1}\equiv0\pmod p\\移项得\\r\cdot i^{-1}\equiv -k\pmod p\\再尝试将r消掉,于是乘以r^{-1}\\i^{-1}\equiv-k\cdot r^{-1}\pmod p\\考虑k=\left\lfloor\dfrac{p}{i}\right\rfloor,r=p\bmod i,带入\\i^{-1}\equiv-\left\lfloor\dfrac{p}{i}\right\rfloor\cdot(p\bmod i)^{-1}\pmod p\\考虑-\left\lfloor\dfrac{p}{i}\right\rfloor \bmod p可以转换为 p-\left\lfloor\dfrac{p}{i}\right\rfloor\\~\\i^{-1}\equiv (p-\left\lfloor\dfrac{p}{i}\right\rfloor)(p\bmod i)^{-1}\pmod p 考虑求i的乘法逆元,则有∃k,r∈Z,p=k⋅i+r,显然k⋅i+r≡0(modp)将同余方程两边同时乘以i的逆元i−1k⋅(i⋅i−1)+r⋅i−1≡0(modp)k+r⋅i−1≡0(modp)移项得r⋅i−1≡−k(modp)再尝试将r消掉,于是乘以r−1i−1≡−k⋅r−1(modp)考虑k=⌊ip⌋,r=pmodi,带入i−1≡−⌊ip⌋⋅(pmodi)−1(modp)考虑−⌊ip⌋modp可以转换为p−⌊ip⌋ i−1≡(p−⌊ip⌋)(pmodi)−1(modp)
考虑使用
i
n
v
i
inv_i
invi 表示
i
i
i在
p
p
p意义下的乘法逆元,将
(
m
o
d
p
)
\pmod p
(modp)提出来,得
i
n
v
i
=
(
p
−
⌊
p
i
⌋
)
(
p
m
o
d
i
)
−
1
m
o
d
p
inv_i=(p-\left\lfloor\dfrac{p}{i}\right\rfloor)(p\bmod i)^{-1}\bmod p
invi=(p−⌊ip⌋)(pmodi)−1modp
这就是逆元的递推式,我们就可以线性求逆元了。
#include<bits/stdc++.h>
using namespace std;
int p;
int inv[100010];
int main()
{
cin>>p;
inv[1]=1;
for(int i=2;i<=p;i++)
inv[i]=(p-p/i)*inv[p%i]%p;
for(int i=1;i<=p;i++)
cout<<inv[i]<<endl;
return 0;
}
当然,我们也可以考虑利用费马小定理来求乘法逆元
由
于
当
p
为
质
数
时
,
有
a
p
≡
a
(
m
o
d
p
)
∴
a
p
−
1
≡
1
(
m
o
d
p
)
⇔
a
⋅
a
p
−
2
≡
1
(
m
o
d
p
)
由于当p为质数时,有a^p\equiv a\pmod p\\ \therefore a^{p-1}\equiv 1\pmod p\Leftrightarrow a\cdot a^{p-2}\equiv 1\pmod p
由于当p为质数时,有ap≡a(modp)∴ap−1≡1(modp)⇔a⋅ap−2≡1(modp)
因此有当
p
p
p为质数时,
a
p
−
2
m
o
d
p
a^{p-2}\bmod p
ap−2modp是
a
a
a在
m
o
d
p
\bmod p
modp意义下的乘法逆元。
我们可以使用快速幂优化求
a
p
−
2
a^{p-2}
ap−2的过程,因此我们可以得到一个
Θ
(
n
log
2
n
)
\Theta(n\log_2n)
Θ(nlog2n)求逆元的算法。
#include<bits/stdc++.h>
#define int long long
using namespace std;
long long n,p;
long long inv[30000010];
long long ksm(int a,int b)
{
long long ans=1;
while(b)
{
if(b&1) ans=ans*a%p;
a=a*a%p;
b>>=1;
}
return ans;
}
signed main()
{
cin>>n>>p;
cout<<1<<'\n';
for(int i=2;i<=n;i++)
{
cout<<ksm(i,p-2)<<'\n';
}
return 0;
}
例题
https://www.luogu.com.cn/problem/P3811
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!