中国剩余定理 (韩信点兵定理)
给出一系列线性同余方程:
x≡a[1](mod m[1])
x≡a[2](mod m[2])
x≡a[3](mod m[3])
…
求x的最小值
令M=m[1]∗m[2]∗…∗m[n]
令M[i]=M/m[i], 因为m[]中的数两两互质,所以M[i]与m[i]互质,所以可以用扩欧求出M[i]的逆元
t[i]是M[i]在模m[i]下的逆元,即M[i]∗t[i]≡1(mod m[i])
x=∑a[i]M[i]t[i] 余数分乘积逆元
void exgcd(LL a, LL b, LL &x, LL &y) {//
if (!b) x = 1, y = 0;
else {
exgcd(b, a % b, y, x);
y -= a / b * x;
}
}
int main() {
cin >> n;
LL M = 1;
for (int i = 0; i < n; ++ i) {
cin >> m[i] >> a[i];
M *= m[i]; //读入mi的同时计算M
}
LL res = 0;
for (int i = 0; i < n; ++ i) {
LL Mi = M / m[i]; //计算Mi = M/mi
LL ti, y;
//这一步是求逆元,根据逆元公式的衍生公式可以得到 ti * Mi + y * mi = 1
exgcd(Mi, m[i], ti, y);
res += a[i] * Mi * ti; //计算的同时累加到res中(上述公式里有个sum需要累加)
}
cout << (res % M + M) % M << endl; //对于任意x+kM都是满足要求的解,但目标是输出最小的正整数x,因此取模即可
return 0;
}