給定 k 個方程:x ≡ rᵢ (mod mᵢ)。求最小非負整數解 x,無解輸出 -1。
mᵢ 不一定互質,故為線性同餘方程組,需用EXCRT (Extended Chinese Remainder Theorem) 求解。
合併 x ≡ r₁ (mod m₁) 和 x ≡ r₂ (mod m₂)。
設 x = m₁·p + r₁ = m₂·q + r₂ → m₁·p - m₂·q = r₂ - r₁。
這是關於 p, q 的線性不定方程。設 g = gcd(m₁, m₂)。
有解條件:g | (r₂ - r₁)。
若有解,通解為 p = p₀ + (m₂/g)·t,代回得新同餘式:
x ≡ r₁ + m₁·p₀ (mod lcm(m₁, m₂)) // 其中 p₀ 為 m₁·p ≡ r₂-r₁ (mod m₂) 的一個解
r = r₁, m = m₁i = 2..k:
m·p ≡ rᵢ - r (mod mᵢ)g = exgcd(m, mᵢ, x, y),得 m·x + mᵢ·y = g(rᵢ - r) % g != 0 → 無解p₀ = x * ((rᵢ - r) / g) % (mᵢ / g) (調整為正)r = r + m * p₀, m = lcm(m, mᵢ) = m / g * mᵢr = (r % m + m) % m 保證非負r 即最小非負解#include <bits/stdc++.h>
using namespace std;
using int64 = long long;
int64 exgcd(int64 a, int64 b, int64& x, int64& y) {
if (b == 0) { x = 1; y = 0; return a; }
int64 g = exgcd(b, a % b, x, y);
int64 t = x; x = y; y = t - a / b * y;
return g;
}
// 合併 x ≡ r1 (mod m1) 和 x ≡ r2 (mod m2)
// 返回 {new_r, new_m},無解返回 {-1, -1}
pair merge(int64 r1, int64 m1, int64 r2, int64 m2) {
int64 x, y;
int64 g = exgcd(m1, m2, x, y); // m1*x + m2*y = g
int64 diff = r2 - r1;
if (diff % g != 0) return {-1, -1}; // 無解
int64 m2_g = m2 / g;
// p0 = x * (diff/g) mod (m2/g)
int64 p0 = (x * (diff / g)) % m2_g;
if (p0 < 0) p0 += m2_g;
int64 new_r = r1 + m1 * p0;
int64 new_m = m1 / g * m2; // lcm
new_r %= new_m;
if (new_r < 0) new_r += new_m;
return {new_r, new_m};
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int k;
while (cin >> k) {
int64 r, m;
cin >> m >> r; // 注意輸入順序:m r
bool ok = true;
for (int i = 1; i < k; ++i) {
int64 m2, r2;
cin >> m2 >> r2;
if (!ok) continue;
auto [nr, nm] = merge(r, m, r2, m2);
if (nr == -1) ok = false;
else { r = nr; m = nm; }
}
cout << (ok ? r : -1) << '\n';
}
return 0;
}
| 點 | 說明 |
|---|---|
| 輸入順序 | 題目給 mᵢ rᵢ,非標準 rᵢ mᵢ |
| 溢出處理 | 用 __int128 計算 m1 * p0 和 m1/g * m2 |
| 負數模修正 | (x % mod + mod) % mod |
| 多組輸入 | EOF 結束,每組獨立處理 |