欧几里得算法(辗转相除法)
内容
g c d ( a , b ) = g c d ( b , a m o d b ) , g c d ( a , 0 ) = a gcd(a,b) = gcd(b,a \bmod b),\ gcd(a,0)=a gcd(a,b)=gcd(b,amodb), gcd(a,0)=a
应用
求两数的最大公因数
证明
大致思路:分为两步,首先证明
g
c
d
(
a
,
b
)
gcd(a,b)
gcd(a,b) 是
b
b
b 和
a
m
o
d
b
a \bmod b
amodb 的一个公因数,
然后利用反证法证明
g
c
d
(
a
,
b
)
gcd(a,b)
gcd(a,b) 是
b
b
b 和
a
m
o
d
b
a \bmod b
amodb 的最大公因数
步骤1
设
c
=
a
m
o
d
b
c=a \bmod b
c=amodb,
k
=
⌊
a
b
⌋
k=\Big\lfloor \dfrac{a}{b} \Big\rfloor
k=⌊ba⌋
则 c = a − b k c=a-bk c=a−bk ①
设 a = k 1 ⋅ g c d ( a , b ) a=k_1 \cdot gcd(a,b) a=k1⋅gcd(a,b) ②, b = k 2 ⋅ g c d ( a , b ) b=k_2 \cdot gcd(a,b) b=k2⋅gcd(a,b) ③
将 ②③ 代入 ①,得 c = k 1 ⋅ g c d ( a , b ) − k ⋅ k 2 ⋅ g c d ( a , b ) c=k_1 \cdot gcd(a,b) - k \cdot k_2 \cdot gcd(a,b) c=k1⋅gcd(a,b)−k⋅k2⋅gcd(a,b)
提取公因数 g c d ( a , b ) gcd(a,b) gcd(a,b),得 c = g c d ( a , b ) ( k 1 − k ⋅ k 2 ) c=gcd(a,b)(k_1-k \cdot k_2) c=gcd(a,b)(k1−k⋅k2)
此时可知 g c d ( a , b ) ∣ c gcd(a,b) | c gcd(a,b)∣c,证得 g c d ( a , b ) gcd(a,b) gcd(a,b) 是 b b b 和 a m o d b a \bmod b amodb 的一个公因数
步骤2
假设
k
1
−
k
⋅
k
2
=
q
t
k_1 - k \cdot k_2 = qt
k1−k⋅k2=qt,
k
1
=
p
t
k_1=pt
k1=pt,
t
∈
Z
,
t
>
1
t \in Z, t > 1
t∈Z,t>1
而我们知道, a = k 1 ⋅ g c d ( a , b ) a=k_1 \cdot gcd(a,b) a=k1⋅gcd(a,b) ②, b = k 2 ⋅ g c d ( a , b ) b=k_2 \cdot gcd(a,b) b=k2⋅gcd(a,b) ③
解得 a = ( p + q ) ⋅ t ⋅ g c d ( a , b ) a=(p+q) \cdot t \cdot gcd(a,b) a=(p+q)⋅t⋅gcd(a,b), b = p t ⋅ g c d ( a , b ) b=pt \cdot gcd(a,b) b=pt⋅gcd(a,b)
容易看出 g c d ( a , b ) = t ⋅ g c d ( a , b ) gcd(a,b)=t \cdot gcd(a,b) gcd(a,b)=t⋅gcd(a,b),而 t ≠ 1 t \neq 1 t=1,不成立
算法实现
int gcd(int a, int b)
{
return !b ? a : gcd(b, a % b);
}
扩展欧几里得算法
内容
裴蜀定理(贝祖定理): a , b ∈ Z , ∃ x , y ∈ Z , a x + b y = g c d ( a , b ) a,b\in Z, \exist \ x,y\in Z, ax+by=gcd(a,b) a,b∈Z,∃ x,y∈Z,ax+by=gcd(a,b)
应用
在求解两数最大公因数的同时,
求出 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b) 的整数解 a , b a,b a,b
证明
大致思路:利用数学归纳法,分为两步,先证明
a
=
g
c
d
(
a
,
b
)
,
b
=
0
a=gcd(a,b),b=0
a=gcd(a,b),b=0 时的情况,
然后推广到一般情况, 利用模数的定义对参数进行替换,从而计算出通式
步骤1
当
a
=
g
c
d
(
a
,
b
)
,
b
=
0
a=gcd(a,b),b=0
a=gcd(a,b),b=0 时,可以解得
x
=
1
,
y
=
0
x=1,y=0
x=1,y=0,此时方程有解
步骤2
假设对于
∀
a
,
b
,
a
x
+
b
y
=
g
c
d
(
a
,
b
)
\forall a,b, ax+by=gcd(a,b)
∀a,b,ax+by=gcd(a,b) 都有解
则 b x 1 + ( a m o d b ) ⋅ y 1 = g c d ( b , a m o d b ) bx_1+(a \bmod b)\cdot y_1=gcd(b, a \bmod b) bx1+(amodb)⋅y1=gcd(b,amodb) ① 成立
而 a m o d b = a − ⌊ a b ⌋ ⋅ b a \bmod b=a-\Big\lfloor \dfrac{a}{b} \Big\rfloor \cdot b amodb=a−⌊ba⌋⋅b ②
结合①②两式,化简得出 a y 1 + b ( x 1 − ⌊ a b ⌋ ⋅ y 1 ) ay_1+b(x_1-\Big\lfloor \dfrac{a}{b} \Big\rfloor \cdot y_1) ay1+b(x1−⌊ba⌋⋅y1),此时 x = y 1 , y = x 1 − ⌊ a b ⌋ ⋅ y 1 x=y1,\ y=x_1-\Big\lfloor \dfrac{a}{b} \Big\rfloor \cdot y_1 x=y1, y=x1−⌊ba⌋⋅y1,方程有解
算法实现
void exgcd(int a, int b, int &d, int &x, int &y)
{
if (!b) {d = a, x = 1, y = 0;} //对应上面证明的特殊情况
else
{
exgcd(b, a % b, d, x, y);
int tmpx = x, tmpy = y; // 已经计算完的上一层的 x, y, 对应证明中的 x1, y1
x = tmpy, y = tmpx - (a / b) * tmpy; // 计算本层的 x, y
}
}
乘法逆元(数论中的倒数)
内容
若 a x ≡ 1 ( m o d n ) ax\equiv1\pmod n ax≡1(modn), g c d ( a , b ) = 1 gcd(a,b)=1 gcd(a,b)=1,此时 x x x 为 a a a 的逆元,记为 a − 1 a^{-1} a−1( a a a 也为 x x x 的逆元),也可以称 x x x 为 a a a 在 ( m o d n ) \pmod n (modn) 意义下的倒数
应用
由于 a b ( m o d n ) ≠ a m o d n b m o d n \dfrac{a}{b}\pmod n\neq \dfrac{a\bmod n}{b\bmod n} ba(modn)=bmodnamodn,
但利用乘法逆元则可以求解 a b ( m o d n ) \dfrac{a}{b}\pmod n ba(modn),方法如下:
求出 b b b 在 ( m o d n ) \pmod n (modn) 意义下的倒数 b − 1 b^{-1} b−1,然后计算 a b − 1 m o d n ab^{-1}\bmod n ab−1modn 即为正确答案
算法实现
扩展欧几里得法
原理
由乘法逆元定义可知, a x m o d n = 1 ax \bmod n = 1 axmodn=1
由此推出, ∃ k , a x = n k + 1 \exist k,\ ax=nk + 1 ∃k, ax=nk+1
移项,得出 a x − n k = 1 ax-nk=1 ax−nk=1,这时已经变成了形如 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b) 的方程
此时需要满足 g c d ( a , n ) = 1 gcd(a,n)=1 gcd(a,n)=1,即可对方程求解
解为 x , k x,k x,k,其中 x x x 即为 a a a 的乘法逆元
代码实现
与上方扩展欧几里得的运算过程相同,只不过在主函数中调用 e x g c d exgcd exgcd 函数的时候需要保证 g c d ( a , b ) = 1 gcd(a,b)=1 gcd(a,b)=1,最终取 x x x 的结果
费马小定理法
原理
根据费马小定理, ∀ a ∈ N ∗ , p ∈ P , g c d ( a , p ) = 1 \forall a \in N^*,p \in P,gcd(a,p)=1 ∀a∈N∗,p∈P,gcd(a,p)=1,有 a p − 1 ≡ 1 ( m o d p ) a^{p-1} \equiv 1 \pmod p ap−1≡1(modp)
和乘法逆元的定义式进行对比,可得 a x ≡ a p − 1 ( m o d p ) ax \equiv a^{p-1} \pmod p ax≡ap−1(modp)
化简得 x ≡ a p − 2 ( m o d p ) x \equiv a^{p-2} \pmod p x≡ap−2(modp)
即可得出 a p − 2 m o d p a^{p-2} \bmod p ap−2modp 为 a a a 的乘法逆元
代码实现
即求一个数的 p − 2 p-2 p−2 次幂,需要用到快速幂算法
递推算法(Luogu P3811)
原理
已知 1 − 1 ≡ 1 ( m o d p ) 1^{-1} \equiv 1 \pmod p 1−1≡1(modp)
设 k = ⌊ p i ⌋ k= \Big\lfloor \dfrac{p}{i} \Big\rfloor k=⌊ip⌋, r = p m o d i r=p \bmod i r=pmodi
则 k i + r ≡ 0 ( m o d p ) ki+r \equiv 0 \pmod p ki+r≡0(modp)
将上式乘 ( i r ) − 1 (ir)^{-1} (ir)−1,得 k r − 1 + i − 1 ≡ 0 ( m o d p ) kr^{-1}+i^{-1} \equiv 0 \pmod p kr−1+i−1≡0(modp)
解得 i − 1 ≡ − k ⋅ r − 1 i^{-1} \equiv -k \cdot r^{-1} i−1≡−k⋅r−1,即 i − 1 ≡ − ⌊ p i ⌋ ⋅ ( p m o d i ) − 1 ( m o d p ) i^{-1} \equiv - \Big\lfloor \dfrac{p}{i} \Big\rfloor \cdot (p \bmod i)^{-1} \pmod p i−1≡−⌊ip⌋⋅(pmodi)−1(modp)
得出 i i i 的逆元为 ( − ⌊ p i ⌋ ⋅ ( p m o d i ) − 1 ) m o d p \Big(- \Big\lfloor \dfrac{p}{i} \Big\rfloor \cdot (p \bmod i)^{-1} \Big)\bmod p (−⌊ip⌋⋅(pmodi)−1)modp
卢卡斯定理
内容
C n m = ∏ i = 0 k C n i m i ( m o d p ) C_n^m=\prod\limits_{i=0}^{k}C_{n_i}^{m_i} \pmod p Cnm=i=0∏kCnimi(modp)