求解:
M a1 (b1)
M a2 (b2)
M a3 (b3)
........
对于 上述式子我们可以拆成 :
M = b1 * p + a1 = b2 * q + a2
左右移项得到:
b1 * p - b2 * q = a2 - a1
可以发现 这就是一个同余方程:
a = b1 , b = b2 , x = p , y = q , c = a2 - a1
我们就可以用扩展欧几里得算法得到:
p 与 q 的特解 x , y。
同时 p 与 q 的通解也可以获得:p = x + (k * b) / gcd(a,b) ,q = y + (k * a) / gcd(a,b)
得到新的同余方程:
M = b1 * ( x + k * b / gcd(a,b)) + a1
将原来的 a = b1 , b = b2 , x = p , y = q , c = a2 - a1 。替换回来:
M = b1 * ( p + k * b2 / gcd(b1,b2) ) + a1
化简:因为:b1 * b2 /gcd(b1,b2) =lcm(b1,b2)
所以:M = k * lcm(b1,b2) + p * b1 + a1
得到:新的 a3 = p * b1 + a1 ,b3 = lcm(b1,b2) 。
这样合并 n - 1次即为答案。
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL)
#define int long long
const int N=5e4+100;
namespace crt{int bi[N],ai[N]; //ai==a ,bi=m1;int n;int mul(int a, int b ,int p){a%=p,b%=p;int z = (long double) a / p * b;int res = (unsigned long long) a * b - (unsigned long long) z * p;return (res + p) % p;}int exgcd(int a, int b, int &x, int &y) {if(b == 0){x = 1; y = 0;return a;}int d = exgcd(b, a % b, x, y);int z = x;x = y;y = z - (a / b) * x;return d;}int excrt()//拓展中国剩余定理{int x, y, k;int M = bi[1], ans = ai[1];//第一个方程的特解for(int i = 2; i <= n; ++ i) {int a = M, b = bi[i], c = (ai[i] - ans % b + b) % b;int d = exgcd(a, b, x, y);int bg = b / d;//lcmif(c % d != 0) return 1e18; //判断是否无解,然而这题其实不用x = mul(x, c / d, bg);//快速乘模板ans += x * M;//更新前k个方程组的答案M *= bg;//M为前k个m的lcmans = (ans % M + M) % M;}ans = (ans % M + M) % M;//if(ans == 0) ans = M;//视情况而定,等于0的时候是因为给定的模数均为1,此时答案应该取任意值均可,而不是只有解 0 ,有时需要特判一下。return ans;}
};
void solve() {int n;cin >> n;crt::n = n;for (int i = 1; i <= n; i++) {int x, y;cin >> x >> y;crt::bi[i] = x;crt::ai[i] = y;}cout << crt::excrt() << '\n';
}
signed main() {IOS;int t = 1;//cin >> t;while (t--) {solve();}return 0;
}