模运算
加减
理解加减法的最好方法就是假设你坐在一辆无限长的火车上,每节车厢有10000个座位,编号从No.0000
到No.9999
。
每当你从No.9999
的座位向前移动1步,你就到达了下一节车厢的第一个座位(No.0000
)。
print((9999+1) % 10000)
# 0
同样地,如果你从No.0000
的座位向后移动1步,你就到达了上一节车厢的最后一个座位(No.9999
)。
print((0-1) % 10000)
# 9999
这就是%
(模运算符)具体怎么工作的。
+
(加法)表示你需要向前移动多少步;
-
(减法)表示你需要向后移动多少步;
乘除
理解乘除最好的方法就是把数字看作是一个集合,比如9 = [3, 3]
,12 = [2, 2, 3]
。
乘法的本质就是把两个集合合并在一起,比如9 * 12 = [2, 2, 3, 3, 3]
。
除法的本质就是把两个集合相减,12=[2,2,3] 和 9=[3,3] 相减,结果:912=[3,3][2,2,3]=[3][2,2]。
基于上述基本事实,可以推导出许多非常有用的定理。
- a⋅bmodp=(amodp)⋅(bmodp)modp
- (xamodp)bmodp=xa⋅bmodp
互质
两个数的最大公约数为1时,这两个数互质。
所有的合数都是由质数相乘得到的。
所以:
- 对于质数:任意两个都是互质的,因为他们本身就是最小单元
- 比如 3=[3] 和 17=[17]。
- 对于合数:当组成合数 a 和 b 的两个质数集合 A 和 B 没有任何共同元素时,a 和 b 互质。
- 比如 8=[2,2,2] 和 15=[3,5],他们没有任何共同元素,所以 8 和 15 互质。
同余
同余就是两个数余数相同,比如 7mod15≡22mod15,他俩对15取模之后的结果都是 7。
本质上 7+15⋅kmod15≡7mod15, k∈Z。
费马小定理
当 a, p 互质时,有下列公式成立:
ap−1modp≡1modp证明过程可以参考这个视频:
首先证明当 p 和 互质时,a⋅rmodp, r∈[1,(p−1)] 是对数集 [1,(p−1)] 的重排列。
假设存在 r1,r2∈[1,p−1],r1=r2, 使得 a⋅r1modp=a⋅r2modp ,则:
a⋅(r1−r2)modp≡0modp明显不存在这样的 r1,r2 ,证毕。
则:
ap−1⋅(p−1)!modp≡(p−1)!modpap−1modp≡1modp模逆元
当 a⋅bmodp=1 时,b=a−1 就是 a 的模逆元。
用费马小定理可以快速求模逆元:
a⋅bmodp=1a⋅bmodp=ap−1modpbmodp=ap−2modp举个例子:a=7,p=13,则 a−1=713−2mod13=2
用 python 中的 pow
函数可以快速计算模逆元。更多求模逆元的方法可以参考algodoc的文章。
欧拉函数
对正整数n,欧拉函数 φ(n) 是小于等于 n 的正整数中与n互质的数的数目。
欧拉函数是费马小定理的延伸,欧拉函数(Euler’s totient function)通常用符号 ϕ(n) 表示,它表示小于等于 n 且与n互质的正整数的个数。其公式在数学上可以表示为:
定义公式
ϕ(n)=np∣n∏(1−p1)其中:
- p表示n的所有不同的素因子。
- p∣n表示p是n的一个因子。
分解步骤
如果n的素因子分解为:
n=p1k1p2k2⋯pmkm则欧拉函数可以计算为:
ϕ(n)=n(1−p11)(1−p21)⋯(1−pm1)计算示例
对于 n=12:
- 分解 n=22⋅31。
- 计算:
ϕ(12)=12(1−21)(1−31)=12⋅21⋅32=4因此,欧拉函数 ϕ(12)=4。
性质
素数的欧拉函数
- 如果 n = p 是一个素数,则:ϕ(p)=p−1
因为所有的数 1,2,…,p−1 都与 p 互质。
幂次的欧拉函数
- 如果n=pk且p是素数,则: ϕ(pk)=pk(1−p1)=pk−pk−1,因为pk中被p整除的数有pk−1个。
乘积性质
- 如果m和n互质(即gcd(m,n)=1),则: ϕ(mn)=ϕ(m)⋅ϕ(n)
- 例子: ϕ(12)=ϕ(3⋅4)=ϕ(3)⋅ϕ(4)=2⋅2=4。
累加性质
- 如果n是一个正整数,则所有小于n的正整数中互质数的个数加起来为: ∑d∣nϕ(d)=n,其中d∣n表示d是n的一个正因子。
- 例子: 对n=6 ,其因子为1,2,3,6,计算ϕ(1)+ϕ(2)+ϕ(3)+ϕ(6): 1+1+2+2=6
费马小定理延伸
aϕ(n)≡1(modn) (如果 gcd(a,n)=1)欧几里得算法
欧几里得算法是一种用于计算两个数的最大公约数的算法。它的基本原理是,两个整数的最大公约数等于其中较小的数和两数的差的最大公约数。
证明:
假设 A>B, A 和 B 的最大公约数是 N,则:C=A−B=N⋅(a−b),显而易见 A,B,C 的最大公约数都是 N。
通过以上不断地求 C,即可快速算出两个超大数的最大公约数。
参考资料