解线性同余方程【exgcd】

本文介绍如何利用扩展欧几里得算法(exgcd)解决线性同余方程ax ≡ b (mod m)的问题。通过裴蜀定理分析解的存在性和表达式,并给出C++代码实现,处理数据范围不超过10^5,且ai, bi, mi在2*10^9以内的情况。" 106585434,7951077,模拟Spring IoC:Bean注解含参方法处理,"['java', 'spring', 'IoC', '依赖注入']

Date:2022.03.31
题目描述:
给定 n 组数据 ai,bi,mi,对于每组数求出一个 xi,使其满足 ai×xi≡bi(modmi),如果无解则输出 impossible。
输入格式
第一行包含整数 n。
接下来 n 行,每行包含一组数据 ai,bi,mi。
输出格式
输出共 n 行,每组数据输出一个整数表示一个满足条件的 xi,如果无解则输出 impossible。
每组数据结果占一行,结果可能不唯一,输出任意一个满足条件的结果均可。
输出答案必须在 int 范围之内。
数据范围
1≤n≤105,
1≤ai,bi,mi≤2×109
输入样例:
2
2 3 6
4 3 5
输出样例:
impossible
-3

思路:由裴蜀定理,若ax+byax+byax+by有解,则一定存在一组解(x0,y0)(x_0,y_0)(x0,y0)使得ax0+by0==gcd(a,b);ax_0+by_0==gcd(a,b);ax0+by0==

扩展欧几里得算法可用于求解同余方程 \(ax \equiv b \pmod{m}\),以下是具体方法及原理: ### 原理 同余方程 \(ax \equiv b \pmod{m}\) 等价于存在整数 \(y\),使得 \(ax - b = my\),即 \(ax + my = b\)。因此,求解同余方程 \(ax \equiv b \pmod{m}\) 就转化为求解线性不定方程 \(ax + my = b\) 的整数 \(x\) 和 \(y\)。 ### 步骤 1. **使用扩展欧几里得算法求解 \(ax + my = \gcd(a, m)\) 的一组特 \(x_0\) 和 \(y_0\)** 扩展欧几里得算法是在欧几里得算法的基础上,不仅求出 \(\gcd(a, m)\),还能求出满足 \(ax + my = \gcd(a, m)\) 的整数 \(x\) 和 \(y\)。以下是扩展欧几里得算法的代码实现: ```cpp #include <iostream> using namespace std; int exgcd(int a, int b, int &x, int &y) { if (!b) { x = 1, y = 0; return a; } int d = exgcd(b, a % b, y, x); y -= a / b * x; return d; } ``` 2. **判断方程是否有** 方程 \(ax + my = b\) 有的充要条件是 \(b\) 能被 \(\gcd(a, m)\) 整除,即 \(b \% \gcd(a, m) == 0\)。若不满足该条件,则方程无。 3. **求出 \(ax + my = b\) 的一组特** 若方程有,设 \(d = \gcd(a, m)\),则 \(ax + my = b\) 的一组特 \(x_1\) 和 \(y_1\) 可由 \(ax + my = d\) 的特 \(x_0\) 和 \(y_0\) 得到: \(x_1 = x_0 \times \frac{b}{d}\) \(y_1 = y_0 \times \frac{b}{d}\) 4. **求出同余方程的最小非负整数** 同余方程 \(ax \equiv b \pmod{m}\) 的通为 \(x = x_1 + k \times \frac{m}{d}\)(\(k\) 为整数)。为得到最小非负整数,可对 \(x_1\) 进行如下处理: \(x = (x_1 \% \frac{m}{d} + \frac{m}{d}) \% \frac{m}{d}\) ### 完整代码示例 ```cpp #include <iostream> using namespace std; // 扩展欧几里得算法 int exgcd(int a, int b, int &x, int &y) { if (!b) { x = 1, y = 0; return a; } int d = exgcd(b, a % b, y, x); y -= a / b * x; return d; } // 求解同余方程 ax ≡ b (mod m) int solveCongruence(int a, int b, int m) { int x, y; int d = exgcd(a, m, x, y); if (b % d != 0) { return -1; // 无 } int k = b / d; x *= k; m /= d; x = (x % m + m) % m; return x; } int main() { int a, b, m; cin >> a >> b >> m; int result = solveCongruence(a, b, m); if (result == -1) { cout << "无" << endl; } else { cout << "最小非负整数为: " << result << endl; } return 0; } ``` ### 复杂度分析 - **时间复杂度**:扩展欧几里得算法的时间复杂度与欧几里得算法相同,为 \(O(\log \min(a, m))\)。 - **空间复杂度**:主要为递归调用栈的空间,空间复杂度为 \(O(\log \min(a, m))\)。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值