本文分成以下四个部分,全部都跟取余有关:
- 引理证明
- 介绍快速幂取余
- 了解数论中的欧拉定理
- 模幂运算
如果你只想看快速幂取余的部分,可以直接看第二部分。
目标一:证明积的取余等于取余的积的取余
数学描述为:
(
a
⋅
b
)
%
p
=
(
(
a
%
p
)
⋅
(
b
%
p
)
)
%
p
(a\cdot b)\%p=((a\%p)\cdot(b\%p))\%p
(a⋅b)%p=((a%p)⋅(b%p))%p
为了简化书写,介绍同余的概念:
若 a % p = b % p a\%p=b\%p a%p=b%p,则称a,b同余,记作 a ≡ b ( m o d    p ) a\equiv b(\mod p) a≡b(modp)或 a ≡ b ( % p ) a\equiv b(\%p) a≡b(%p)
同余的基本性质:
- ( a − b ) % p = 0 (a-b)\%p=0 (a−b)%p=0,即 p ∣ ( a − b ) p\mid(a-b) p∣(a−b),即 p p p能整除 a − b ⇔ a ≡ b ( m o d    p ) a-b\Leftrightarrow a\equiv b(\mod p) a−b⇔a≡b(modp)
- 对称性: a ≡ b ( m o d    p ) ⇔ b ≡ a ( m o d    p ) a\equiv b(\mod p)\Leftrightarrow b\equiv a(\mod p) a≡b(modp)⇔b≡a(modp)
- 传递性:若 a ≡ b ( m o d    p ) a\equiv b(\mod p) a≡b(modp)且 b ≡ c ( m o d    p ) b\equiv c(\mod p) b≡c(modp),则 a ≡ c ( m o d    p ) a\equiv c(\mod p) a≡c(modp)
定理: 若 a ≡ b ( m o d    p ) 且 c ≡ d ( m o d    p ) 若a\equiv b(\mod p)且c\equiv d(\mod p) 若a≡b(modp)且c≡d(modp),则
- a + c ≡ b + d ( m o d    p ) a+c\equiv b+d(\mod p) a+c≡b+d(modp)
- a − c ≡ b − d ( m o d    p ) a-c\equiv b-d(\mod p) a−c≡b−d(modp)
- a ⋅ c ≡ b ⋅ d ( m o d    p ) a\cdot c\equiv b\cdot d(\mod p) a⋅c≡b⋅d(modp)
- a / c ≡ b / d ( m o d    p ) a/c\equiv b/d(\mod p) a/c≡b/d(modp)
只证 a ⋅ c ≡ b ⋅ d ( m o d    p ) a\cdot c\equiv b\cdot d(\mod p) a⋅c≡b⋅d(modp)供参考,其余类似证得。
证明:
因为 c ≡ d ( m o d    p ) c\equiv d(\mod p) c≡d(modp)
由性质1得 ( c − d ) % p = 0 (c-d)\%p=0 (c−d)%p=0
也有 [ a ⋅ ( c − d ) ] % p = 0 [a\cdot (c-d)]\%p=0 [a⋅(c−d)]%p=0
即 ( a ⋅ c − a ⋅ d ) % p = 0 (a\cdot c-a\cdot d)\%p=0 (a⋅c−a⋅d)%p=0
所以 a ⋅ c ≡ a ⋅ d ( m o d    p ) a\cdot c\equiv a\cdot d(\mod p) a⋅c≡a⋅d(modp)
同理可得 a ⋅ d ≡ b ⋅ d ( m o d    p ) a\cdot d\equiv b\cdot d(\mod p) a⋅d≡b⋅d(modp)
最后由传递性得 a ⋅ c ≡ b ⋅ d ( m o d    p ) a\cdot c\equiv b\cdot d(\mod p) a⋅c≡b⋅d(modp)
显然
a
≡
a
%
p
(
m
o
d
  
p
)
和
b
≡
b
%
p
(
m
o
d
  
p
)
a\equiv a\%p(\mod p)和b\equiv b\%p(\mod p)
a≡a%p(modp)和b≡b%p(modp)
故由上面得定理可得:
(
a
⋅
b
)
%
p
=
(
(
a
%
p
)
⋅
(
b
%
p
)
)
%
p
(a\cdot b)\%p=((a\%p)\cdot(b\%p))\%p
(a⋅b)%p=((a%p)⋅(b%p))%p,故得证。
目标二:理解快速幂取余
快速幂取余又叫蒙哥马利算法。
这部分内容主要借鉴于一篇我认为是最好的讲解快速幂取余原理的博客。
目标:快速求出
a
b
%
c
a^{b}\%c
ab%c,其中
b
b
b可以是一个很大的数。
代码如下:
int quick_mod(int a,int b,int c) {
int A = 1; // 结果的保存,就是 An,初始化一下
int T = a % c; //首先计算 T0 的值,用于 Tn 的递推
while(b != 0){
if(b&1){
A = (A * T) % c;
}
b >>= 1;
T = (T * T) % c; // 更新 T,如果下一位是 1 就可以用这个算 A
}
return A;
}
目标三:了解数论中的欧拉定理
欧拉函数:
φ
(
n
)
\varphi(n)
φ(n)表示小于n的正整数中与n互质的数的个数。
欧拉定理:若n,a为正整数,且n,a互素,即gcd(a,n) = 1,则
a
φ
(
n
)
≡
1
(
m
o
d
  
n
)
a^{\varphi(n)}\equiv1(\mod n)
aφ(n)≡1(modn)