模运算以及乘法逆元

基本的模运算

a,b,p 均为整数

模 p 加法:(a+b)%p

模 p 减法:(ab)%p

模 p 乘法:(ab)%p ## Notes

同余式:正整数 a,b 对 p 取模,它们的余数相同,记作 ab(mod p)

基本性质

1. 若 p=a-b, 则 abmodp 例如 114mod7

2. 传递性:若 abmodp bcmodp, 则 acmodp

运算规则

(a+b)modp=(amodp+bmodp)modp(ab)modp=(amodpbmodp)modp(ab)modp=(amodpbmodp)modp(ab)modp=((amodp)b)modp

结合律

((a+bmodp+c)modp=(a+(b+c)modp)modp((abmodpc)modp=(a(bc)modp)modp

交换律

分配律

(((a+b)modp)c)modp=((ac)modp+(bc)modp)modp

重要定理

abmodp 则对于任意的 c, 都有 (a+c)(b+c)modp

abmodp 则对于任意的正整数 c, 都有 (ac)(bc)modp

abmodp,cdmodp 则对于任意的 c, 都有 (a+c)(b+d)modp,(ac)(bd)modp,(ac)(bd)modp

乘法逆元

定义

如果 ax≡1 (mod p), 且 gcd (a,p)=1(a 与 p 互质),则称 a 关于模 p 的乘法逆元为 x。

例子

例如:4 关于 1 模 7 的乘法逆元为多少?

4X≡1 mod 7

这个方程等价于求一个 X 和 K,满足

4X=7K+1

其中 X 和 K 都是整数。

若 ax≡1 (mod f), 则称 a 关于 1 模 f 的乘法逆元为 x。也可表示为 ax≡1 (mod f)。

当 a 与 f 互素时,a 关于模 f 的乘法逆元有解。如果不互素,则无解。如果 f 为素数,则从 1 到 f-1 的任意数都与 f 互素,即在 1 到 f-1 之间都恰好有一个关于模 f 的乘法逆元。

例如,求 5 关于模 14 的乘法逆元:

14=5*2+4

5=4*1+1

说明 5 与 14 互素,存在 5 关于 14 的乘法逆元。

1=5-4=5-(14-5*2)=5*3-14

因此,5 关于模 14 的乘法逆元为 3。

扩展欧几里得定理

欧几里得算法 (辗转相除法)

即以除数和余数反复做除法运算,当余数为 0 时,取当前算式除数为最大公约数

证明

引理 1:若 d 是 a 和 b 的公约数,那么 d 也是 b 和 c 的公约数(c=a% b)

引理 2:若 d 是 b 和 c 的公约数 (c=a% b) 那么 d 也是 b 和 c 的公约数

定理:两个整数的最大公约数等于其中较小的那个数和两数相除余数的最大公约数。

证法:

a 可以表示成 a=kb+r(a,b,k,r 均为正整数且 r<b)

假设 d 是 a,b 的一个公约数,记作 d|a,d|b,即 a 和 b 都可以被 d 整除

r=akb,两边同时除以 d,r/d=a/dkb/d,由等式右边可知 m=r/d 为整数,因此 d|r

因此 d 也是 b,a mod b 的公约数

因 (a,b) 和 (b,a mod b) 的公约数相等,则其最大公约数也相等

1
2
def gcd(a,b):
return gcd(b,a%b) if b else a

时间复杂度为 O (log n)

本体

设两个式子 ax+by=gcd(a,b)bx+(amodb)y=gcd(b,amodb) 由欧几里得算法知:gcd(a,b)=gcd(b,amodb)

所以 ax+by=bx+(amodb)y

amodb=akb

其中 k=[a/b]

所以有 ax+by=bx+(akb)y

展开移项得:ax+by=ay+b(xky)

根据对应系数关系,可以设

x=yy=xky 来进一步求一个可行解

递归地使用 x'、y' 表示 “上一步” 的 x、y,就能递归地把问题转化为 bx+(amodb)y=gcd(b,amodb) x 和 y 会不断减小,类似 gcd () 的递归终点,当扩展欧几里得算法 exgcd () 的 aax+by=gcd(a,b) 中的 b 为 0 时,可以得到递归终点的 x=1,y=0,层层回溯套用前面等式 x=yy=xky 就能得到 ax+by=gcd(a,b) 的一组可行解

算法

对于任意两个整数 a, b,必存在整数 x, y,使得 ax + by = gcd (a,b) 成立,求出整数解 x, y,可以得到 gcd (a,b).

具体步骤

1. 定义 x1 = 1, y1 = 0, x2 = 0, y2 = 1

2. 若 b ≠ 0,使用带余除法,用 b 除以 a 得到余数 r;否则转到第 4 步

3. 用 b 代替 a, 用 r 代替 b, 令 x1, y1, x2, y2 = x2, y2, x1 - q·x2, y1 - q·y2,重复第 2 步

4.a 的值就是最大公约数 d,x1 和 y1 的值就是所求 x 和 y

代码实现

1
2
3
4
5
6
def exgcd(a,b):
if(b==0):
return 1,0,a
x,y,g=exgcd(b,a%b)
x,y=y,(x-(a//b)*y)
return x,y,g

模拟矩阵运算的扩展欧几里得算法:https://www.cnblogs.com/kentle/p/14975039.html

求逆元

逆元:a 关于模 b 得逆元整数 d 满足 admodb1

扩展欧几里得:求方程 ax+by=gcd(a,b) 的一组可行解

关系:(ad)(mod b)1,等价于 ad-kb=1, 其中 k 为未知整数

设 d 为 x,-k 为 y,则 adkb=1 转化为 ax+by=1

求出 x 即可得到 a 关于模 b 的逆元

当 x 为负值的时候

代码实现

1
2
3
4
5
6
7
8
def exgcdinv(a,b):
if(b==0):
return 1,0,a
x,y,g=exgcdinv(b,a%b)
t=x
x=y
y=t-a//b*y
return x,y,g

时间复杂度为 O (log n)(斐波那契复杂度)

补充

1. 显然,当 x 求出负值时,由于乘法逆元应为正,经验证,若 admodb1,d=x+b(证明推导留待时候)

2.python 自带的 pow 函数 pow (a,b,c),当 b 为 - 1 的时候,可以求 a 关于模 c 的乘法逆元

存在即可求

费马小定理

前置知识

费马小定理

对于整数 a 与质数 b,若 a 与 b 互质,则有 ab1modb1

快速幂取模

两数之积取模等于对两数分别取模然后对积取模 (ab)modp=((amodp)(bmodp))modp

代码实现

1
2
3
4
5
6
7
8
def powmod(a,n,mod):
ret=1
while n>0:
if n%2 ==1:
ret=a*a % mod
a=a*a % mod
n//=2
return ret

求逆元

ab1modb1 等价于 aab2modb1

显然 ab2 就是 a mod b 的逆元

用 b-2 和 b 代替快速幂取模中的 n 和 mod:

1
2
def Fermatinv(a,b):
return powmod(a,b-2,b)

时间复杂度:大约 O (log b)

适用范围:在模数 b 是质数时

Stein 算法

只有整数的移位和加减法,便于大素数求公约数

前置知识

gcd(a,a)=a,即一个数和他自身的公约数是其自身

gcd(ka,kb)=kgcd(a,b) 也就是最大公约数运算和倍乘运算可以交换,特殊的,当 k=2 时,说明两个偶数的最大公约数必然能被 2 整除

算法步骤

假设 A1=A,B1=B,C1=1

for n=1,2,3...do:

1. 若 An=0 或 Bn=0,则 max (An,Bn)*Cn 为最大公约数,算法结束

2. 若 An 和 Bn 均为偶数,则 An+1= 若 An/2,Bn+1=Bn/2,Cn+1=2*Cn

3. 若 An 为偶数,Bn 为奇数,则 An+1=An/2,Bn+1=Bn

4. 若 An 为奇数,Bn 为偶数,则 An+1=An,Bn+1=Bn/2

5. 若 An,Bn 均为奇数,则 An+1=|An-Bn|/2

Bn+1=min(An,Bn),Cn+`=Cn

代码实现

1
2
3
4
5
6
7
8
9
10
11
def Stein(a,b):
if a<b:
a,b=b,a
if(b==0):return a
if a%2==0 and b%2 == 0:
return 2*Stein(a>>1,b>>1)
if a%2==0:
return Stein(a>>1,b)
if b%2==0:
return Stein(a,b>>1)
return Stein(abs(a-b)>>1,min(a,b))