
点击查看代码
#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 inline mod(LL a, LL b)
{
return ((a % b) + b) % b;
}
int main()
{
int n;
cin >> n;
LL a1, m1;
cin >> a1 >> m1;
bool has_answer = true;
for (int i = 0; i < n - 1; i ++) {
LL a2, m2;
cin >> a2 >> m2;
LL k1, k2;
LL d = exgcd(a1, a2, k1, k2);
if ((m2 - m1) % d) {
has_answer = false;
break;
}
k1 *= (m2 - m1) / d;
LL t = a2 / d;
k1 = mod(k1, t);
m1 = a1 * k1 + m1;
a1 = abs(a1 / d * a2);
}
if (has_answer) {
cout << mod(m1, a1) << endl;
}
else puts("-1");
return 0;
}
- 中国剩余定理

① 计算所有模数的乘积 n
② 对于第 i 个方程,计算 mi=nni,计算 mi 在模 ni 意义下的逆元 m−1,计算 ci=mi⋅m−1i
③ 方程组的唯一解为:x=∑ki=1ai⋅ci (mod n)
- 扩展中国剩余定理
① 对于每两个式子 x≡m1(moda1) ,x≡m2(moda2) ,可以写成 x=k1⋅a1+m1 ,x=k2⋅a2+m2 ,右边两个式子都等于 x ,可以得到 k1⋅a1+m1=k2⋅a2+m2 ,整理得到 k1⋅a1+k2⋅(−a2)=m2−m1
② 使用扩展欧几里得算法可得到 k′1,k′2 ,使得 k′1⋅a1+k′2⋅a2=gcd(a1,−a2) , 若 m2−m1 不是 gcd(a1,−a2) 的倍数,则说明无解;否则,记 gcd(a1,−a2) 为 d ,那么 k1,k2 可用 k′1,k′2 表示为:k1=m2−m1d⋅k′1 ,k2=m2−m1d⋅k′2,也就是找到了 k1 和 k2 的特解
③ 让 k1=k1(特解)+k⋅a2d ,k2=k2(特解)+k⋅a1d ,在 k 取任意值时,代入 k1⋅a1+k2⋅(−a2)=m2−m1 可以发现新的 k1, k2 仍然满足等式,也就是说已经找到 k1, k2 的通解公式,要找一个最小的非负整数 x ,只需让 k1=k1mod∣∣a2d∣∣, k2=k2mod∣∣a1d∣∣ ,即可找到最小的 k1, k2 的解
④ 将 k1=k1+k⋅a2d 代入 x=k1⋅a1+m1 中,可得 x=(k1+k⋅a2d)⋅a1+m1=k1⋅a1+m1+k⋅a1⋅a2d=k1⋅a1+m1+k⋅lcm(a1,a2) ,令 a0=lcm(a1,a2), m0=k1⋅a1+m1 ,那么 x=k⋅a0+m0 ,至此,完成了前两个方程的合并,再用新得到的方程和 x=k3⋅a3+m3 合并,以此类推,就可以把所有的方程合并,最后得到一个式子 x=k⋅a+m ,最小正整数解为 mmoda 对应的最小正整数余数
- inline 是内联函数,可以解决一些频繁调用的小函数大量消耗栈空间(栈内存)的问题,inline 的使用是有所限制的,inline 只适合函数体内代码简单的函数使用,不能包含复杂的结构控制语句例如 while、switch,并且内联函数本身不能是直接递归函数(即,自己内部还调用自己的函数)。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!