裴蜀定理+拓展欧几里得+费马小定理+中国剩余定理
裴蜀定理

拓展欧几里得
gcd
递归写法
if b == 0:
return a
return gcd(b, a % b)
def gcd(a,b):
if b == 0:
return a
return gcd(b, a % b)
然而python递归深度有上限,因此可以用安全的写法
def gcd(a, b):
while b != 0:
a, b = b, a % b
return a
exgcd

def exgcd(a, b):
"""
返回 (g, x, y)
满足 a*x + b*y = g = gcd(a,b)
"""
if b == 0:
# 递归终点: a*1 + 0*0 = a
return (a, 1, 0)
else:
g, x1, y1 = exgcd(b, a % b)
x = y1
y = x1 - (a // b) * y1
return (g, x, y)
求模逆元模板
a和m互质时,逆元inv=pow(a,-1,m)可以直接用
def mod_inverse(a,m):
g,x,y = exgcd(a,m)
if g != 1:
return None #逆元不存在,a和m不互质
else:
# 将x调整到 0~m-1 的正范围
inv = (x % m + m) % m
return inv
求出不定方程 ax+by=c 的完整通解

#前置条件:必须满足 gcd(a,b)整除 c,方程才有解
import math
def solve_equation(a,b,c):
"""
解 ax + by = c
返回:(g, x0, y0, a1, b1)
x0,y0 :一组特解
a1 = a/g, b1 = b/g
通解公式:
x = x0 - b1 * t
y = y0 + a1 * t
t∈Z
"""
g, x0, y0 = exgcd(a,b)
if c % g != 0:
print("方程无整数解!")
return None
# 把 ax+by=g 的解放大,得到 ax+by=c 的特解
k = c // g
x0 = x0 * k
y0 = y0 * k
a1 = a // g
b1 = b // g
return (g, x0, y0, a1, b1)
费马小定理

中国剩余定理

模数两两互质
def exgcd(a, b):
if b == 0:
return a, 1, 0
d, y, x = exgcd(b, a % b)
y -= a // b * x
return d, x, y
def crt(a, m):
"""
a: 余数列表
m: 模数列表,要求两两互质
返回最小非负解 x
"""
M = 1
for num in m:
M *= num
res = 0
for ai, mi in zip(a, m):
Mi = M // mi
d, x, y = exgcd(Mi, mi)
res = (res + ai * Mi * x) % M
return res % M
# 测试样例 x ≡2 mod3, x≡3 mod5, x≡2 mod7
if __name__ == "__main__":
a = [2, 3, 2]
m = [3, 5, 7]
print(crt(a, m)) # 输出 23
扩展中国剩余定理 EXCRT(不全互质)
def exgcd(a, b):
if b == 0:
return a, 1, 0
d, y, x = exgcd(b, a % b)
y -= a // b * x
return d, x, y
def excrt(a, m):
"""
a:余数数组
m:模数数组
返回:(x, M) 解 x ≡ res (mod M)
无解返回 (-1, -1)
"""
x, M = 0, 1
for ai, mi in zip(a, m):
# 合并 x ≡ x (mod M), x ≡ ai (mod mi)
d, p, q = exgcd(M, mi)
c = ai - x
if c % d != 0:
return -1, -1 # 无解
lcm = M // d * mi
tmp = (c // d * p) % (mi // d)
x = x + tmp * M
M = lcm
x = (x % M + M) % M
return x, M
# 测试
if __name__ == "__main__":
a = [2, 3, 2]
m = [3, 5, 7]
ans, mod = excrt(a, m)
print(ans)
浙公网安备 33010602011771号