一阶线性同余方程 逆

一阶线性同余方程

给定 \(a,b,m\) ,求整数 \(x\) ,满足 \(ax\equiv b\ (mod \ m)\)

这说明 \(ax-b\)\(m\) 的倍数,设为 \(-y\) 倍,这就得到二元线性丢番图方程 \(ax+my=b\)

所以,求解一阶线性同余方程等价于二元线性丢番图方程。

定理

\(a,b,m\in N\)\(m>0\)\((a,m)=d\)

\(d\nmid b\) ,则 \(ax\equiv b\ (mod \ m)\) 无解。

\(d\mid b\) ,则 \(ax\equiv b\ (mod \ m)\)\(d\) 个模 \(m\) 不同余的解。

推论

$a $ 和 \(m\) 互质时,因为 \(d=(a,m)=1\) ,所以线性同余方程 \(ax\equiv b\ (mod \ m)\) 有唯一的模 \(m\) 不同余的解。

这条推论在求解同余方程有很重要的作用。先求逆,再用逆求 \(x\)


(一)求单个逆

扩展欧几里得

对于 \(ax\equiv1\ (mod \ m)\) ,即丢番图方程 \(ax+my=1\) ,

先用扩展欧几里得算法算出 \(ax+my=1\) 的一个特解 \(x_0\) ,通解 \(x=x_0+mn\)

若要求最小整数解,则 \(x=((x_0\ mod \ m) + m)\ mod \ m\)

费马小定理

快速幂求逆元 费马小定理 - AKgrid - 博客园

(二)求多个逆

若要求 \(1\sim n\)\(p\) 所有的逆,用递推法。时间复杂度 \(O(n)\)

首先,\(i=1\) 时,\(i^{-1} = 1\) 。当 \(i > 1\) 时,

(1)设 \(p/i=k\) ,余数为 \(r\) ,所以 \(k\ \cdot\ i+r\equiv0\ (mod\ p)\)

(2)等式两边同乘 \(i^{-1} \ \cdot\ r^{-1}\) ,得 \(k\ \cdot\ r^{-1} +i^{-1}\equiv 0\ (mod\ p)\)

(3)移项得 \(i^{-1}\equiv-k\ \cdot\ r^{-1}\ (mod\ p)\) ,代入 \(k=p/i\) ,得 \(i^{-1}\equiv-p/i\ \cdot\ r^{-1}\ (mod\ p)\) ;

(4)由于 \(0\equiv p\ (mod \ p)\) ,叠加后得到 \(i^{-1}\equiv(p-p/i)\ \cdot\ r^{-1}\ (mod\ p)\)

(三)用逆求解同余方程

对于 \(ax\equiv b\ (mod \ m)\),直接两边同时乘 \(a^{-1}\) ,就得到方程的解 \(x\equiv a^{-1}b\ (mod \ m)\)

其中,\(a\ \cdot\ a^{-1}\equiv 1\ (mod\ m)\),可以利用这一点简单求逆。

这里假设了 \((a,m)\mid b\) ,即同余方程有解。

例如,\(8x\equiv 22\ (mod\ 31)\) ,两边同时乘以 \(8\)\(31\) 的逆 \(4\)\(8 \times 4 \equiv 1 \ (mod \ 31)\) ),得到 \(x\equiv 88\ (mod \ 31)\equiv 26\ (mod \ 31)\)


[AcWing878] 线性同余方程

题目描述

给定 \(n\) 组数据 \(a_i,b_i,m_i\),对于每组数求出一个 \(x_i\),使其满足 \(a_i \times x_i \equiv b_i \pmod {m_i}\),如果无解则输出 impossible

输入格式

第一行包含整数 \(n\)

接下来 \(n\) 行,每行包含一组数据 \(a_i,b_i,m_i\)

输出格式

输出共 \(n\) 行,每组数据输出一个整数表示一个满足条件的 \(x_i\),如果无解则输出 impossible

每组数据结果占一行,结果可能不唯一,输出任意一个满足条件的结果均可。

输出答案必须在 \(int\) 范围之内。

数据范围

\(1 \le n \le 10^5\),
\(1 \le a_i,b_i,m_i \le 2 \times 10^9\)

输入样例:

2
2 3 6
4 3 5

输出样例:

impossible
-3

算法

注意结果开 \(long \ long\)

C++ 代码

#include<bits/stdc++.h>
using namespace std;
int n, x, y;
using LL = long long ;
int exgcd(int a, int b, int &x, int &y)
{
    if (!b)
    {
        x = 1, y = 0;
        return a;
    }
    int x1, y1;
    int d = exgcd(b, a % b, x1, y1);
    x = y1, y = x1 - a / b * y1;
    return d;
}

int main()
{
    cin >> n;
    while (n --)
    {
        int a, b, m;
        cin >> a >> b >> m;
        int d = exgcd(a, m, x, y);
        if (b % d) puts("impossible");
        else 
        {
            x = (LL)x * b / d % m;
            cout << x << endl;
        }
    }
    return 0;
}

P3811 【模板】模意义下的乘法逆元

题目背景

这是一道模板题

题目描述

给定 \(n,p\)\(1\sim n\) 中所有整数在模 \(p\) 意义下的乘法逆元。

这里 \(a\)\(p\) 的乘法逆元定义为 \(ax\equiv1\pmod p\) 的解。

输入格式

一行两个正整数 \(n,p\)

输出格式

输出 \(n\) 行,第 \(i\) 行表示 \(i\) 在模 \(p\) 下的乘法逆元。

输入输出样例 #1

输入 #1

10 13

输出 #1

1
7
9
10
8
11
2
5
3
4

说明/提示

\(1 \leq n \leq 3 \times 10^6\)\(n < p < 20000528\)

输入保证 $ p $ 为质数。

算法

模版题,线性求多个逆元。

代码

#include <iostream>
using namespace std;

const int N = 3e6 + 10;
long inv[N];

int main() {
  int n, p;
  scanf("%d%d", &n, &p);
  inv[1] = 1;
  puts("1");
  for (int i = 2; i <= n; i++)
    printf("%ld\n", inv[i] = (long)p - (p / i) * inv[p % i] % p);
}
posted @ 2025-02-13 19:59  AKgrid  阅读(39)  评论(0)    收藏  举报