EXCRT学习笔记
扩展中国剩余定理(EXCRT)
\[\begin{cases}
x \equiv b_1 \pmod{a_1} \\
x \equiv b_2 \pmod{a_2} \\
\vdots \\
x \equiv b_n \pmod{a_n}
\end{cases}
\]
观察这个式子,当模数不互质的时候中国剩余定理(CRT)已经不再适用,这时就请出比CRT功能更强的EXCRT,在竞赛中尤为常用。
下面朴素介绍:
做法其实就是把式子合二为一,做 \(n-1\) 次
比如合并
\[\begin{cases}
x \equiv b_1 \pmod{a_1} \\
x \equiv b_2 \pmod{a_2} \\
\end{cases}
\]
显然的,存在 \(p, q \in Z\), 使得
\[ x + a1*p = b1 \\
x + a2*q = b2\\
\]
消去$ x $ :
\[ a1 * p - a2 *q = b1 - b2
\]
这是形如 \(ax+by = c\) 的不定方程, 自然的,我们用裴祖定理判断有无解,用EXGCD求出\(a1 * p - a2 * q = gcd(a1, a2)\) 的一组特解,再乘上 \(\frac{b1 - b2}{gcd(a1, a2)}\) 可以得到特解 \(p_0, q_0\) , 于是就可以得到原方程的通解 :
\[ p = p_0 + \frac{a2}{gcd(a1, a2)} * k \\
q = q_0 + \frac{a1}{gcd(a1, a2)} * k
\]
又因为前面已知 $x = b1 - a1 * p $, 带入p可以得到 :
\[x = b1 - a1 * (p_0 + \frac{a2}{gcd(a1, a2)} * k)
\\
= b1 - a1 * p0 - \frac{a1 \ a2}{gcd(a1, a2)} * k
\\
= b1 - a1 * p0 - Lcm(a1, a2) * k
\]
最终我们得到了一个新的同余方程 :
\[ x \equiv b1 - a1 * p0 \pmod{Lcm(a1, a2)}
\]
代码展示 【模板】扩展中国剩余定理(EXCRT)
#include<bits/stdc++.h>
using namespace std;
// #define int long long
#define int __int128
#define rep(i, l, r) for(int i = (l); i <= (r); ++ i)
#define per(i, r, l) for(int i = (r); i >= (l); -- i)
#define fi first
#define se second
#define endl '\n'
#define pii pair<int, int>
#define pb push_back
int exgcd(int a,int b, int &x, int &y) {
if(b == 0) {
x = 1;
y = 0;
return a;
} else {
int t = exgcd(b, a % b, y, x);
y = y - a / b * x;
return t;
}
}
void Jail() {
long long n;
cin >> n;
int A = 1, B = 0;
rep(i, 1, n) {
long long a, b;
cin >> a >> b;
int p, q;
int g = exgcd(A, a, p, q);
// if(abs(B - b) % g != 0) {
// cout << -1 << endl;
// return ;
// }
p = (B - b) / g * p;
B = B - A * p;
A = a / g * A;
B = (B % A + A) % A;
}
long long ans = (B % A + A) % A;
cout << ans << endl;
}
signed main() {
// freopen("a.in", "r", stdin);
// freopen("a.out", "w", stdout);
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int T = 1;
// cin >> T;
while(T --) Jail();
return 0;
}
例题
题解后面补

浙公网安备 33010602011771号