AcWing 204. 表达整数的奇怪方式
. 表达整数的奇怪方式
一、题目描述
给定 个整数 和 ,求一个最小的非负整数 ,满足 。
输入格式
第 行包含整数 。
第 行:每 行包含两个整数 和 ,数之间用空格隔开。
输出格式
输出最小非负整数 ,如果 不存在,则输出 。
如果存在 ,则数据保证 一定在 位整数范围内。
数据范围
输入样例:
2
8 7
11 9
输出样例:
31
二、解题思路
中国剩余定理
作用:求组线性同余方程的通解
使用前提:对于,其中若 两两互质,则可以使用 中国剩余定理 来求解。
形式: $$ \large (S) : \left{\right.$$
公式
其中是的逆元,(除了以外的乘积),
扩展中国剩余定理
本题中并未说之间两两互质,需要重新推导:
推导(按题目的来)
【一会是除数,是余数,一会又是是余数,是除数,真是太了,本来就不咋会,还故意扰乱我的思路!】
先计算两个线性同余方程组的解,之后依此类推
① 可以写成 ③
② 可以写成 ④
③=④ ⟶⑤
根据 裴蜀定理,当为的倍数时,方程⑤有无穷组整数解
而可以用拓展欧几里得算法来解,即
:中的和通解公式是什么?
结论
解释:如果我们知道一组特解,那么,可以通过任意整数倍的缩放,使得缩放倍,缩放倍,得到的新依然是方程的解。
证明:
设的通解为,的通解为,的特解为,的特解为
解释:这么写方便些,不想再写什么了,太麻烦~
则:
傻瓜问题为什么互质?
答:在方程组⑥中根据裴蜀定理的推论(互质的充要条件是存在整数使)从而得出它两互质.
到此证明完毕,回归正题,求解本题。
将通解代入③得
令,,就和原来的方程一个样子,但化简掉了一个方程,问题变得简单些,只要不断的合并,最终就可以得到答案
依此迭代,经过次后可以将个线性同余方程合并为一个方程,求最小解,只需最后即可
三、实现代码
#include <iostream>
using namespace std;
typedef long long LL;
LL exgcd(LL a, LL b, LL &x, LL &y) {
if (!b) {
x = 1, y = 0;
return a;
}
LL d = exgcd(b, a % b, y, x);
y -= a / b * x;
return d;
}
LL n, a1, m1, a2, m2, k1, k2;
int main() {
cin >> n;
cin >> a1 >> m1; // 读入第一个方程
n--; // 共n-1个方程
while (n--) {
cin >> a2 >> m2;
// 开始合并
// a1*k1+(-a2)*k2=m2-m1
// ① 求a1*k1+(-a2)*k2=gcd(a1,-a2)的解,视k1=x,k2=y
LL d = exgcd(a1, -a2, k1, k2);
if ((m2 - m1) % d) { // 如果不是0,则无解
cout << -1;
exit(0);
}
// ② 求 a1*k1+(-a2)*k2=m2-m1 的一组解,需要翻 (m2-m1)/d倍
k1 *= (m2 - m1) / d;
// ③ 求最小正整数解
int t = abs(a2 / d);
k1 = (k1 % t + t) % t;
// ④ 更新a1和m1,准备下一轮合并
m1 = k1 * a1 + m1;
a1 = abs(a1 / d * a2);
}
// 输出,m1是一个解,不是最小整数解,需要模a1
cout << (m1 % a1 + a1) % a1;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
2016-10-08 工资系统解决办法
2016-10-08 控制其它程序