給定 a, b, c, k,求最小正整數 x 滿足:
c * x ≡ b - a (mod 2^k)
即解線性同餘方程 a'x ≡ b' (mod n),其中 a'=c、b'=b-a、n=2^k。
方程 ax ≡ b (mod n) 有解 ⇔ d = gcd(a, n) 整除 b。
若 d = ax₁ + ny(由擴展歐幾里得得 x₁),則一特解為:
x₀ = x₁ * (b/d) (mod n)
通解為 x = x₀ + t*(n/d),最小正整數解在 [0, n/d) 區間內。
d = gcd(a, n) ⇒ ∃x₁,y: d = ax₁ + nyn:d ≡ ax₁ (mod n)b = kd ⇒ b ≡ kd ≡ kax₁ ≡ a(kx₁) (mod n)x = kx₁ = x₁*(b/d) 為一解。#include <iostream>
using namespace std;
#define L long long
L Egcd(L a, L b, L &x, L &y) { // 擴展歐幾里得
if (b == 0) { x = 1; y = 0; return a; }
L d = Egcd(b, a % b, x, y);
L tp = x; x = y; y = tp - (a / b) * y;
return d;
}
void MLE(L a, L b, L n) { // 解模線性方程
L x, y, d = Egcd(a, n, x, y);
if (b % d == 0) {
L x0 = (b / d * x) % n + n; // 確保非負
cout << x0 % (n / d) << endl; // 最小正解在 n/d 範圍內
} else {
cout << "FOREVER" << endl; // 無解
}
}
int main() {
L a, b, c; int k;
while (cin >> a >> b >> c >> k) {
if (!a && !b && !c && !k) break;
MLE(c, b - a, 1LL << k);
}
return 0;
}
| 輸入 | 輸出 | 說明 |
|---|---|---|
| 3 3 2 16 | 0 | b-a=0, x=0 為解 |
| 3 7 2 16 | 2 | 2*2≡4≡7-3(mod 65536) |
| 7 3 2 16 | 32766 | 2*32766≡65532≡3-7(mod 65536) |
| 3 4 2 16 | FOREVER | gcd(2,65536)=2 不整除 1 |
1LL << k 計算 2^k 避免溢位。x0 % (n/d) 直接取得最小正解(群論:解集合形成 d 個等價類,每類週期 n/d)。