同余问题共7part,我的博客链接:
逆元
定义: gcd ( a , m ) = 1 , a x ≡ 1 ( m o d m ) \gcd(a,m)=1,ax\equiv 1(\mod m) gcd(a,m)=1,ax≡1(modm) , x x x 的解即为 a a a 的逆。
分数逆元: a b m o d m = a ⋅ b − 1 m o d m \frac{a}{b}\mod m=a\cdot b^{-1} \mod m bamodm=a⋅b−1modm
方法一:费马小定理
定理: gcd ( a , m ) = 1 , m 为 素 数 ⇒ a m − 1 ≡ 1 ( m o d m ) ⇔ a ⋅ a m − 2 ≡ 1 ( m o d m ) \gcd(a,m)=1,m为素数\Rightarrow a^{m-1}\equiv 1(\mod m)\Leftrightarrow a\cdot a^{m-2}\equiv 1(\mod m) gcd(a,m)=1,m为素数⇒am−1≡1(modm)⇔a⋅am−2≡1(modm)
用快速幂求 a p − 2 a^{p-2} ap−2 即可。
inline ll inv(int a) { return qpow(a, m - 2, m); }
方法二:拓展欧几里得
a ⋅ i n v ( a ) ≡ 1 ( m o d m ) a\cdot inv(a)\equiv 1(\mod m) a⋅inv(a)≡1(modm) ,拓展欧几里得解出答案,注意防止负数即可。
inline ll inv(ll a)
{
ll x, y, d;
exgcd(a, m, d, x, y);
return d == 1 ? (x % m + m) % m : -1; // 不互质无解
}
方法三:线性递推
将
m
m
m 表示为
m
=
k
x
+
y
m=kx+y
m=kx+y ,其中
k
=
⌊
m
/
x
⌋
,
y
=
m
%
x
k=\lfloor m/x\rfloor,y=m\%x
k=⌊m/x⌋,y=m%x 。
则
k
x
+
y
≡
0
(
m
o
d
m
)
kx+y\equiv 0(\mod m)
kx+y≡0(modm) ,同乘
i
n
v
(
x
)
i
n
v
(
y
)
inv(x)inv(y)
inv(x)inv(y) ,则有
k
⋅
i
n
v
(
y
)
+
i
n
v
(
x
)
≡
0
(
m
o
d
m
)
k\cdot inv(y)+inv(x)\equiv 0(\mod m)
k⋅inv(y)+inv(x)≡0(modm)
得
i
n
v
(
x
)
≡
−
k
⋅
i
n
v
(
y
)
(
m
o
d
m
)
inv(x)\equiv -k\cdot inv(y)(\mod m)
inv(x)≡−k⋅inv(y)(modm)
令
i
n
v
(
x
)
=
−
k
⋅
i
n
v
(
y
)
=
−
⌊
m
/
x
⌋
⋅
i
n
v
(
m
%
x
)
m
o
d
m
inv(x)=-k\cdot inv(y)=-\lfloor m/x\rfloor\cdot inv(m\%x)\mod m
inv(x)=−k⋅inv(y)=−⌊m/x⌋⋅inv(m%x)modm
即一个数的逆元可由一个比它小的数的推出来。把负数消掉即可。
注: m m m 可不是素数
// inv[1...last]是1...last的逆元
inline void init(ll inv[], ll last, ll m)
{
inv[1] = 1;
for (ll i = 2ll; i <= last;i++)
inv[i] = (m - m / i) * inv[m % i] % m;
}