中国剩余定理非互质版本
合并方程的思想.求出一元带到原式子中可得到另一元,最终两个方程合并为一个方程.在转换的过程中,要善于换元,如果出现了两个变量,就把其中一个变量作为模数,研究在同余下的意义.
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; ll a[1010], b[1010], n; ll gcd(ll a, ll b) { if (!b) return a; return gcd(b, a % b); } ll exgcd(ll a, ll b, ll &x, ll &y) { if (!b) { x = 1; y = 0; return a; } ll temp = exgcd(b, a % b, x, y), t = x; x = y; y = t - (a / b) * y; return temp; } ll niyuan(ll x, ll mod) { ll px, py, t; t = exgcd(x, mod, px, py); if (t != 1) return -1; return (px % mod + mod) % mod; } bool hebing(ll a1, ll n1, ll a2, ll n2, ll &a3, ll &n3) { ll d = gcd(n1, n2), c = a2 - a1; if (c % d != 0) return false; c = (c % n2 + n2) % n2; n1 /= d; n2 /= d; c /= d; c *= niyuan(n1, n2); c %= n2; //取模,在哪一个模数下就要模哪个,模数要跟着变化. c *= n1 * d; c += a1; n3 = n1 * n2 * d; a3 = (c % n3 + n3) % n3; return true; } ll China() { ll a1 = b[1], n1 = a[1], a2, n2; for (int i = 2; i <= n; i++) { ll a3, n3; a2 = b[i], n2 = a[i]; if (!hebing(a1, n1, a2, n2, a3, n3)) return -1; a1 = a3; n1 = n3; } return (a1 % n1 + n1) % n1; } int main() { scanf("%lld", &n); for (int i = 1; i <= n; i++) scanf("%lld%lld", &a[i], &b[i]); printf("%lld\n", China()); return 0; }