数学:逆元,同余

发布于:2025-06-27 ⋅ 阅读:(15) ⋅ 点赞:(0)

0.引言

本文讲述什么是逆元,如何求逆元。求逆元的两种常规方法。然后知道同余是求逆元的前置知识。所以先说同余,再说逆元。关于求模,看我这篇文章求模

1.同余

定义:若两个整数 a a a b b b 除以正整数 m m m 的余数 r r r 相同,则称作 a a a b b b 同模,记作 a ≡ b    ( m o d    m ) a \equiv b\;(mod\;m) ab(modm)
等价描述: m m m整除 a − b a-b ab,即 m ∣ ( a − b ) m|(a-b) m(ab)

示例:

  • 13 ÷ 12 = 1....1 , 1 ÷ 12 = 0....1 13 \div12=1....1,1\div12=0....1 13÷12=1....11÷12=0....1,两个余数都是1,所以 13 ≡ 1    ( m o d    12 ) 13 \equiv1\;(mod\;12) 131(mod12)
  • 25 ÷ 7 = 3....4 , 11 ÷ 7 = 1....4 25\div7=3....4,11\div7=1....4 25÷7=3....411÷7=1....4,两个余数都是4,所以 25 ≡ 7    ( m o d    4 ) 25\equiv 7\;(mod \;4) 257(mod4)

1.1 同余的基本性质


等价关系性质:
  • 自反性:对于任意整数a,有 a ≡ a    ( m o d    m ) a \equiv a\;(mod\;m) aa(modm)
  • 对称性:若 a ≡ b    ( m o d    m ) , a\equiv b\;(mod\;m), ab(modm) b ≡ a    ( m o d    m ) b\equiv a\;(mod\;m) ba(modm)
  • 传递性:若 a ≡ b ( m o d m ) a \equiv b \pmod{m} ab(modm) b ≡ c ( m o d m ) b \equiv c \pmod{m} bc(modm),则 a ≡ c ( m o d m ) a \equiv c \pmod{m} ac(modm)

代数运算性质:

a ≡ b    ( m o d    m ) , c ≡ d    ( m o d    m ) ; a \equiv b\;(mod\;m),c\equiv d\;(mod\;m); ab(modm)cd(modm);

  • 加减性: a + c ≡ b + d    ( m o d    m ) a+c \equiv b+d\;(mod\;m) a+cb+d(modm) a − c ≡ b − d    ( m o d    m ) a-c \equiv b-d\;(mod\;m) acbd(modm)
  • 乘法性: a ⋅ c ≡ b ⋅ d    ( m o d    m ) a \cdot c\equiv b\cdot d\;(mod\;m) acbd(modm)
  • 幂次性:若n为正整数,则 a n ≡ b n    ( m o d    m ) a^n\equiv b^n\;(mod\;m) anbn(modm)
  • 除法性:若 a ⋅ c ≡ b ⋅ c    ( m o d    m ) , a\cdot c\equiv b\cdot c\;(mod\;m), acbc(modm), g c d ( c , m ) = d gcd(c,m)=d gcd(c,m)=d,则 a ≡ b    ( m o d    m d ) a \equiv b\;(mod\;\frac{m}{d}) ab(moddm)

同余类和剩余系:

  1. 同余类(剩余类):模m同余的所有整数构成一个集合,叫做模m的一个同余类。例如,模2时,所有的偶数都属于同余类 [ 0 ] 2 [0]_2 [0]2,所有的奇数都属于同余类 [ 1 ] 2 [1]_2 [1]2。一般的,模m有m个不同的剩余类,也就是同余类,分别是: [ 0 ] m , [ 1 ] m , [ 2 ] m . . . . [ m − 1 ] m [0]_m,[1]_m,[2]_m....[m-1]_m [0]m[1]m[2]m....[m1]m
  2. 完全剩余系:从每个模 m 的同余类中各取一个数组成的集合,称为模 m 的完全剩余系。例如,模 4 的一个完全剩余系可为 { 0 , 1 , 2 , 3 } \{0, 1, 2, 3\} {0,1,2,3},或 { 5 , − 2 , 7 , 10 } \{5, -2, 7, 10\} {5,2,7,10}(每个数模 4 余 0,1,2,3)。
  3. 简化剩余系(缩系):若同余类中的数与 m 互质,则称该类为简化同余类。从所有简化同余类中各取一个数组成的集合,称为模 m 的简化剩余系,其元素个数为欧拉函数 φ ( m ) \varphi(m) φ(m)。例如,模 6 时,与 6 互质的数为 1,5,故简化剩余系为 { 1 , 5 } \{1, 5\} {1,5} φ ( 6 ) = 2 \varphi(6)=2 φ(6)=2。(不知道什么是欧拉函数的看我这篇博客—还没写)

1.2 解同余线性方程

问题描述:有: a x ≡ b ( m o d m ) ax \equiv b \pmod{m} axb(modm),且 a , b , m a,b,m abm都是整数, m > 0 m>0 m>0,求解 x x x
问题等价于求解 a x + m y = b ax+my=b ax+my=b。其中 (x, y) 是整数解。这是因为 a x ≡ b ( m o d m ) ax \equiv b \pmod{m} axb(modm) 意味着 ax 与 b 的差是 m 的倍数,即存在整数 y 使得 a x − b = m y ax - b = my axb=my,整理后得到 a x + m y = b ax + my = b ax+my=b

下面为解决这个问题步骤:

1.解的存在性
2.使用扩展欧几里算出贝祖系数然后求特解(所以先会介绍这个算法是什么)
3.由特解算通解

  1. 解的存在性(必要性):设 d = g c d ( a , m ) d=gcd(a,m) d=gcd(a,m),方程有解当且仅当 d 整除 b1,记作 ( d ∣ b ) (d \mid b) (db)

证明:首先 a x ≡ b ( m o d m ) ax \equiv b \pmod{m} axb(modm)的等价形式为 a x − b = k m ax-b=km axb=km
a x − b = k m ax-b=km axb=km,则 a x − k m = b ax-km=b axkm=b,d 是 a 和 m 的公约数,即存在整数 a ′ = a / d , m ′ = m / d a' = a/d,m' = m/d a=a/dm=m/d,使得 a = d a ′ , m = d m ′ a = d a',m = d m' a=dam=dm,且 gcd ⁡ ( a ′ , m ′ ) = 1 \gcd(a', m') = 1 gcd(a,m)=1
a = d a ′ , m = d m ′ a = d a',m = d m' a=dam=dm 代入上式: d a ′ x − d m ′ k = b ⇒ d ( a ′ x − m ′ k ) = b d a' x - d m' k = b \quad \Rightarrow \quad d(a' x - m' k) = b daxdmk=bd(axmk)=b
由于 a ′ x − m ′ k a' x - m' k axmk 是整数,记为 t,则 b = d t b = d t b=dt,即 d ∣ b d \mid b db

  1. 扩展欧几里得算法

    扩展欧几里得算法是欧几里得算法(辗转相除法)的扩展,其核心目标是:对于给定的整数 a 和 b,不仅计算它们的最大公约数 d = gcd ⁡ ( a , b ) d = \gcd(a, b) d=gcd(a,b),还找到整数 x 和 y,使得: a x + b y = d ax + by = d ax+by=d其中,整数对 ( x , y ) (x, y) (x,y) 称为贝祖系数
    扩展欧几里得算法不仅能计算 g c d ( a , m ) gcd(a, m) gcd(a,m),还能找到整数 x 0 x_0 x0 y 0 y_0 y0,使得: a ⋅ x 0 + m ⋅ y 0 = gcd ⁡ ( a , m ) a \cdot x_0 + m \cdot y_0 = \gcd(a, m) ax0+my0=gcd(a,m)若 b 是 gcd ⁡ ( a , m ) \gcd(a, m) gcd(a,m) 的倍数(即 b = d ⋅ k b = d \cdot k b=dk,其中 d = gcd ⁡ ( a , m ) d = \gcd(a, m) d=gcd(a,m),则原方程的一个特解为: x = x 0 ⋅ k 和 y = y 0 ⋅ k x = x_0 \cdot k \quad \text {和} \quad y = y_0 \cdot k x=x0ky=y0k

什么是贝祖系数?先看贝祖定理

贝祖定理:对于任意整数 a 和 b,存在整数 x 和 y,使得 a x + b y = gcd ⁡ ( a , b ) ax + by = \gcd(a, b) ax+by=gcd(a,b)。特别地,当 a 和 b 互质时,存在 x 和 y 使得 a x + b y = 1 ax + by = 1 ax+by=1


如何求解?

欧几里得算法基于递归式 gcd ⁡ ( a , b ) = gcd ⁡ ( b , a m o d    b ) \gcd(a, b) = \gcd(b, a \mod b) gcd(a,b)=gcd(b,amodb),而扩展算法在计算 GCD 的同时,通过回溯保存每一步的线性组合系数

先说明一下欧几里得算法的基本流程:
下面是欧几里得算法(辗转相除法)

#include<iostream>
using namespace std;

int gcd(int a,int b)   //递归     示例 a=24   b=9 
{
	if(b==0)
		return a;
	return gcd(b,a%b);
}

int gcd(int a,int b)   //迭代
{
	while(b!=0)
	{
		int temp=b;
		b=a%b;
		a=temp;
	}
	return a;
}

扩展欧几里得算法求贝祖系数:

// 扩展欧几里得算法:求 gcd(a, m) 及贝祖系数 x, y
int extendedGCD(int a, int m, int& x, int& y) //一开始x,y什么值都没有,空
{
    if (m == 0) //此时gcd(a,0)=a,贝祖系数为x=1,y=0.因为a*1+0*0=a
    {
        x = 1;
        y = 0;
        return a;
    }
    int x1, y1;
    int gcd = extendedGCD(m, a % m, x1, y1);
    //m*x1+(a%m)*y1=gcd(m,a%m)

	//通过递归返回的x1,y1计算当前层的贝祖系数x,y
    x = y1;
    y = x1 - (a / m) * y1;
    return gcd;
}

通过贝祖系数求同余方程特解:

  1. 原同余方程 a x ≡ b ( m o d m ) ax \equiv b \pmod{m} axb(modm) 等价于线性不定方程: a x + m y = b ax + my = b ax+my=b当且仅当 gcd ⁡ ( a , m ) ∣ b \gcd(a, m) \mid b gcd(a,m)b 时,方程有解。此时,记 d = gcd ⁡ ( a , m ) d = \gcd(a, m) d=gcd(a,m),则存在整数 k = b d k = \frac{b}{d} k=db,使得 b = d ⋅ k b = d \cdot k b=dk

  2. 将贝祖等式两边同时乘以 k = b d k = \frac{b}{d} k=db a x 0 ⋅ k + m y 0 ⋅ k = d ⋅ k ax_0 \cdot k + my_0 \cdot k = d \cdot k ax0k+my0k=dk,由于 d ⋅ k = b d \cdot k = b dk=b,代入上式得: a ⋅ ( x 0 ⋅ k ) + m ⋅ ( y 0 ⋅ k ) = b a \cdot (x_0 \cdot k) + m \cdot (y_0 \cdot k) = b a(x0k)+m(y0k)=b,对比原方程 a x + m y = b ax + my = b ax+my=b,可以发现: x ′ = x 0 ⋅ k = x 0 ⋅ b d x' = x_0 \cdot k = x_0 \cdot \frac{b}{d} x=x0k=x0db y ′ = y 0 ⋅ k = y 0 ⋅ b d y' = y_0 \cdot k = y_0 \cdot \frac{b}{d} y=y0k=y0db是原方程的一组整数解,即特解。

通解:
对于同余方程 a ⋅ x ≡ b ( m o d m ) a \cdot x \equiv b \pmod{m} axb(modm),转化为线性方程 a ⋅ x + m ⋅ y = b a \cdot x + m \cdot y = b ax+my=b 后。
特解:通过扩展欧几里得算法求得一组特解 ( x 1 , y 1 ) (x_1, y_1) (x1,y1),满足 a ⋅ x 1 + m ⋅ y 1 = b a \cdot x_1 + m \cdot y_1 = b ax1+my1=b
通解:所有解可表示为: x = x 1 + k ⋅ m d , y = y 1 − k ⋅ a d ( k ∈ Z ) x = x_1 + k \cdot \frac{m}{d}, \quad y = y_1 - k \cdot \frac{a}{d} \quad (k \in \mathbb{Z}) x=x1+kdm,y=y1kda(kZ)。其中 d = gcd ⁡ ( a , m ) d = \gcd(a, m) d=gcd(a,m)

通解的推导过程:
( x 1 , y 1 ) (x_1, y_1) (x1,y1) ( x 2 , y 2 ) (x_2, y_2) (x2,y2) 是方程的两组解,则: a ⋅ x 1 + m ⋅ y 1 = b 和 a ⋅ x 2 + m ⋅ y 2 = b a \cdot x_1 + m \cdot y_1 = b \quad \text{和} \quad a \cdot x_2 + m \cdot y_2 = b ax1+my1=bax2+my2=b 两式相减得:
a ( x 2 − x 1 ) + m ( y 2 − y 1 ) = 0 ⇒ a ( x 2 − x 1 ) = − m ( y 2 − y 1 ) a(x_2 - x_1) + m(y_2 - y_1) = 0 \quad \Rightarrow \quad a(x_2 - x_1) = -m(y_2 - y_1) a(x2x1)+m(y2y1)=0a(x2x1)=m(y2y1)
两边除以 d = gcd ⁡ ( a , m ) d = \gcd(a, m) d=gcd(a,m),得: a d ( x 2 − x 1 ) = − m d ( y 2 − y 1 ) \frac{a}{d}(x_2 - x_1) = -\frac{m}{d}(y_2 - y_1) da(x2x1)=dm(y2y1)
由于 a d \frac{a}{d} da m d \frac{m}{d} dm 互质,故 ( x 2 − x 1 ) (x_2 - x_1) (x2x1) 必为 m d \frac{m}{d} dm 的倍数,即: x 2 − x 1 = k ⋅ m d ⇒ x 2 = x 1 + k ⋅ m d x_2 - x_1 = k \cdot \frac{m}{d} \quad \Rightarrow \quad x_2 = x_1 + k \cdot \frac{m}{d} x2x1=kdmx2=x1+kdm
代入原方程得: y 2 = y 1 − k ⋅ a d y_2 = y_1 - k \cdot \frac{a}{d} y2=y1kda

求同余方程特通解:(全部过程代码)

#include <iostream>
#include <vector>
using namespace std;

// 扩展欧几里得算法
int extendedGCD(int a, int m, int& x, int& y) {
    if (m == 0) {
        x = 1;
        y = 0;
        return a;
    }
    int x1, y1;
    int gcd = extendedGCD(m, a % m, x1, y1);
    x = y1;
    y = x1 - (a / m) * y1;
    return gcd;
}

// 求解 ax ≡ b (mod m)
vector<int> solveCongruence(int a, int b, int m) {
    vector<int> solutions;
    int x, y;
    int gcd = extendedGCD(a, m, x, y);
    
    // 检查解的存在性
    if (b % gcd != 0) {
        return solutions; // 无解
    }
    
    // 计算特解并调整到最小非负
    int x0 = x * (b / gcd);
    x0 = (x0 % m + m) % m;
    
    // 生成所有解
    int step = m / gcd;
    for (int k = 0; k < gcd; k++) {
        solutions.push_back((x0 + k * step) % m);
    }
    
    return solutions;
}

int main() {
    int a = 30, b = 6, m = 24;
    vector<int> solutions = solveCongruence(a, b, m);
    
    if (solutions.empty()) {
        cout << "无解" << endl;
    } else {
        cout << "解为: ";
        for (int x : solutions) {
            cout << x << " ";
        }
        cout << endl;
    }
    
    return 0;
}

代码难点就是,回溯的时候,子问题的x,y和原问题的x,y是如何置换的?

扩展欧几里得算法的目标是求解贝祖方程 a ⋅ x + b ⋅ y = gcd ⁡ ( a , b ) a \cdot x + b \cdot y = \gcd(a, b) ax+by=gcd(a,b),根据欧几里得算法的递归性质,我们知道: gcd ⁡ ( a , b ) = gcd ⁡ ( b , a m o d    b ) \gcd(a, b) = \gcd(b, a \mod b) gcd(a,b)=gcd(b,amodb)
因此,假设子问题: 求解 b ⋅ x ′ + ( a m o d    b ) ⋅ y ′ = gcd ⁡ ( b , a m o d    b ) b \cdot x' + (a \mod b) \cdot y' = \gcd(b, a \mod b) bx+(amodb)y=gcd(b,amodb)的解为 (x’, y’),则原问题的解 ((x, y)) 与子问题的解存在以下关系:

  1. a m o d    b a \mod b amodb a m o d    b = a − ⌊ a b ⌋ ⋅ b a \mod b = a - \left\lfloor \frac{a}{b} \right\rfloor \cdot b amodb=abab其中 ⌊ a b ⌋ \left\lfloor \frac{a}{b} \right\rfloor ba 表示 a 除以 b 的商。

  2. 代入子问题的贝祖方程: b ⋅ x ′ + ( a m o d    b ) ⋅ y ′ = gcd ⁡ ( b , a m o d    b ) b \cdot x' + (a \mod b) \cdot y' = \gcd(b, a \mod b) bx+(amodb)y=gcd(b,amodb)
    替换 a m o d    b a \mod b amodb
    b ⋅ x ′ + ( a − ⌊ a b ⌋ ⋅ b ) ⋅ y ′ = gcd ⁡ ( a , b ) b \cdot x' + (a - \left\lfloor \frac{a}{b} \right\rfloor \cdot b) \cdot y' = \gcd(a, b) bx+(abab)y=gcd(a,b)

  3. 整理方程: a ⋅ y ′ + b ⋅ ( x ′ − ⌊ a b ⌋ ⋅ y ′ ) = gcd ⁡ ( a , b ) a \cdot y' + b \cdot (x' - \left\lfloor \frac{a}{b} \right\rfloor \cdot y') = \gcd(a, b) ay+b(xbay)=gcd(a,b)

  4. 对比原问题的贝祖方程: a ⋅ x + b ⋅ y = gcd ⁡ ( a , b ) a \cdot x + b \cdot y = \gcd(a, b) ax+by=gcd(a,b)
    可得:
    x = y ′ , y = x ′ − ⌊ a b ⌋ ⋅ y ′ x = y', \quad y = x' - \left\lfloor \frac{a}{b} \right\rfloor \cdot y' x=y,y=xbay


2.逆元

在模运算中,逆元分为加法逆元和乘法逆元。
这里只介绍乘法逆元.

对于整数a和模数m,若存在整数x满足: a ∗ x ≡ 1 ( m o d    m ) a*x \equiv1(mod\;m) ax1(modm)
则称x是a在模m下的乘法逆元,记作 a − 1 m o d    m a^{-1} mod\;m a1modm

逆元存在当且仅当a和m互质(gcd(a,m)=1)

为什么需要逆元?
因为在模运算中, a b m o d    m \frac{a}{b} mod\;m bamodm 没有定义,所有要把除法转换成乘法,也就是 a b m o d    m = b ∗ a − 1 m o d    m \frac{a}{b} mod\;m=b*a^{-1} mod\;m bamodm=ba1modm
而求 a − 1 a^{-1} a1 可以通过 a ∗ a − 1 ≡ 1 ( m o d    m ) a*a^{-1} \equiv1(mod\;m) aa11(modm) 来求
比如:

计算 6 3 m o d    7 \frac{6}{3} \mod 7 36mod7,等价于 6 ⋅ 3 − 1 m o d    7 6 \cdot 3^{-1} \mod 7 631mod7。由于 3 × 5 = 15 ≡ 1 m o d    7 3 \times 5 = 15 \equiv 1 \mod 7 3×5=151mod7,故 3 − 1 = 5 3^{-1} = 5 31=5,则结果为 6 × 5 = 30 ≡ 2 m o d    7 6 \times 5 = 30 \equiv 2 \mod 7 6×5=302mod7,与实际 6 3 = 2 \frac{6}{3}=2 36=2 一致。

下面是两种方法求逆元


费马小定理求逆元(m必需为质数)

证明看我这篇文章除法求模
原理:若 m 是质数,且 a 不是 m 的倍数,则根据费马小定理: a m − 1 ≡ 1 ( m o d m ) a^{m-1} \equiv 1 \pmod{m} am11(modm)两边同乘 a − 1 a^{-1} a1 得: a − 1 ≡ a m − 2 ( m o d m ) a^{-1} \equiv a^{m-2} \pmod{m} a1am2(modm)

long long quick_pow(long long a, long long b, long long mod)
 {
    long long res = 1;
    while (b) 
    {
        if (b & 1) res = res * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return res;
}

long long mod_inverse(long long a, long long m) {
    if (a % m == 0) return -1;  // 逆元不存在
    return quick_pow(a, m - 2, m);
}

扩展欧几里得求逆元(使用任意互质的a和m)

原理:根据贝祖定理,若 gcd ⁡ ( a , m ) = 1 \gcd(a, m) = 1 gcd(a,m)=1,则存在整数 x , y x, y x,y 使得: a ⋅ x + m ⋅ y = 1 a \cdot x + m \cdot y = 1 ax+my=1两边模 m 得: a ⋅ x ≡ 1 ( m o d m ) a \cdot x \equiv 1 \pmod{m} ax1(modm) 因此 x 即为 a 的逆元。

因为这是贝祖定理的特殊情况,所有操作比较简单。

计算步骤:

  1. 用欧几里得扩展算法求解 a ∗ x + m ∗ y = 1 a*x+m*y =1 ax+my=1 的一组特解
  2. 逆元为 x 0    m o d    m x_0 \;mod\;m x0modm
#include <iostream>
using namespace std;

// 扩展欧几里得算法
long long exgcd(long long a, long long b, long long &x, long long &y) {
    if (b == 0) {
        x = 1;
        y = 0;
        return a;
    }
    long long d = exgcd(b, a % b, y, x);
    y -= a / b * x;
    return d;
}

// 求逆元
long long mod_inverse(long long a, long long m) {
    long long x, y;
    long long d = exgcd(a, m, x, y);
    if (d != 1) return -1;  // 逆元不存在
    return (x % m + m) % m;  // 确保结果为正
}

int main() {
    long long a = 3, m = 7;
    long long inv = mod_inverse(a, m);
    cout << "3的逆元模7是: " << inv << endl;  // 应输出5
    return 0;
}

  1. 若存在整数 k,使得 b = d × k b = d \times k b=d×k,则称 “d 整除 b”,记作 d ∣ b d \mid b db。此时,d 是 b 的约数(因数),b 是 d 的倍数。 ↩︎


网站公告

今日签到

点亮在社区的每一天
去签到