ruye07

导航

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

裴蜀定理

image

拓展欧几里得

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

image

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 的完整通解

image

#前置条件:必须满足 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)

费马小定理

image

中国剩余定理

image

模数两两互质

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)

posted on 2026-09-02 16:13  ruye07  阅读(4)  评论(0)    收藏  举报