同余问题常用定理证明
扩展欧几里得算法
扩展欧几里得定理:设
证明:设
欧几里得算法可知,
即
则
可以通过欧几里得算法递归迭代到
利用归纳法,最后解的大小满足:
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;
}
欧拉定理 & 费马小定理
欧拉定理:若
证明:设
即
根据缩系性质,可约去
费马小定理:若
证明:当
线性同余方程
设
设同余方程有解
反过来,若
int x, y;
int d = exgcd (a, p, x, y);
if (b % d) {
res = -1;
} else {
x *= (b / d);
res = (x % (p / d) + (p / d)) % (p / d);
}
中国剩余定理
中国剩余定理:设
其中
易于验证,上面的解的”叠加“
另一方面,如果
线性同余方程组
模数互质,使用中国剩余定理。
vector <int> A(n), B(n);
LL M = 1;
for (int i = 0; i < n; i ++ ) {
cin >> A[i] >> B[i];
M *= A[i];
}
LL res = 0;
for (int i = 0; i < n; i ++ ) {
LL Mi = M / A[i];
LL ti, x;
exgcd (Mi, A[i], ti, x);
res += B[i] * Mi * ti;
}
cout << (res % M + M) % M << "\n";
在模数不互质的情况下,设其中两个方程分别是
LL res = 0, m1, a1;
cin >> m1 >> a1;
for (int i = 0; i < n - 1; i ++ ) {
LL m2, a2;
cin >> m2 >> a2;
LL k1, k2;
LL d = exgcd (m1, m2, k1, k2);
if ((a2 - a1) % d) {
res = -1;
}
k1 *= (a2 - a1) / d;
k1 = (k1 % (m2 / d) + (m2 / d)) % (m2 / d);
LL m = abs (m1 / d * m2);
a1 = k1 * m1 + a1;
m1 = m;
}
if (res != -1) {
res = (a1 % m1 + m1) % m1;
}
cout << res << "\n";
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步