本文分成以下四个部分,全部都跟取余有关:
- 引理证明
- 介绍快速幂取余
- 了解数论中的欧拉定理
- 模幂运算
如果你只想看快速幂取余的部分,可以直接看第二部分。
目标一:证明积的取余等于取余的积的取余
数学描述为:
(a⋅b)%p=((a%p)⋅(b%p))%p
为了简化书写,介绍同余的概念:
若a%p=b%p,则称a,b同余,记作a≡b(modp)或a≡b(%p)
同余的基本性质:
-
(a−b)%p=0,即 p∣(a−b),即p能整除a−b⇔a≡b(modp)
- 对称性:a≡b(modp)⇔b≡a(modp)
- 传递性:若a≡b(modp)且b≡c(modp),则a≡c(modp)
定理:若a≡b(modp)且c≡d(modp),则
- a+c≡b+d(modp)
- a−c≡b−d(modp)
- a⋅c≡b⋅d(modp)
- a/c≡b/d(modp)
只证a⋅c≡b⋅d(modp)供参考,其余类似证得。
证明:
因为c≡d(modp)
由性质1得(c−d)%p=0
也有[a⋅(c−d)]%p=0
即(a⋅c−a⋅d)%p=0
所以a⋅c≡a⋅d(modp)
同理可得a⋅d≡b⋅d(modp)
最后由传递性得a⋅c≡b⋅d(modp)
显然a≡a%p(modp)和b≡b%p(modp)
故由上面得定理可得:(a⋅b)%p=((a%p)⋅(b%p))%p,故得证。
目标二:理解快速幂取余
快速幂取余又叫蒙哥马利算法。
这部分内容主要借鉴于一篇我认为是最好的讲解快速幂取余原理的博客。
目标:快速求出ab%c,其中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)表示小于n的正整数中与n互质的数的个数。
欧拉定理:若n,a为正整数,且n,a互素,即gcd(a,n) = 1,则aφ(n)≡1(modn)
目标四:模幂运算
