同余问题常用定理证明

扩展欧几里得算法

扩展欧几里得定理:设 \(a\)\(b\) 不全为 \(0\),则存在整数 \(x\)\(y\),使得 \(ax + by = (a, b)\)

证明:设 \(d = (a, b)\),求 \(ax + by = d\) 的一组 \((x, y)\)

欧几里得算法可知,\(bx ^ {\prime} + (a \bmod b) y ^ {\prime} = d\)

\(bx ^ {\prime} + (a - \lfloor \frac{a}{b} \rfloor \cdot b) y ^ {\prime} = d\)\(ay ^ {\prime} + b(x ^ {\prime} - \lfloor \frac {a}{b} \rfloor \cdot y ^ {\prime}) = d\)

\(x = y ^ {\prime}, y = x ^ {\prime} - \lfloor \frac {a} {b} \rfloor \cdot y ^ {\prime}\)

可以通过欧几里得算法递归迭代到 \(a ^ {\prime} = d, b ^ {\prime} = 0\) 时可以得到此时 \(x ^ {\prime} = 1, y ^ {\prime} = 0\),再利用上面推出的 \(x, y\)\(x ^ {\prime}, y ^ {\prime}\) 的关系进一步代入计算,得到 \(ax + by = (a, b)\) 的一组解。

利用归纳法,最后解的大小满足:\(|x| \leq b, |y| \leq a\)

int exgcd (int a, int b, int &x, int &y) {
    if (!b) {
        x = 1, y = 0;
        return a;
    }
    
    int d = exgcd (b, a % b, y, x);

    y -= (a / b) * x;

    return d;
}

欧拉定理 & 费马小定理

欧拉定理:若 \((a, m) = 1\),则 \(a ^ {\varphi (m)} \equiv 1 \pmod{m}\)

证明:设 \(r_{1}, r_{2}, \cdots , r_{\varphi (m)}\) 是模 \(m\) 的缩系,因为 \((a, m) = 1\),所以 \(ar_{1}, ar_{2}, \cdots,r_{\varphi}\) 也是模 \(m\) 的缩系。

\(r_{1}r_{2} \cdots r_{\varphi(m)} \equiv ar_{1} \cdot ar_{2} \cdots ar_{\varphi(m)} \equiv a ^ {\varphi (m)}r_{1}r_{2} \cdots r_{\varphi (m)}\)

根据缩系性质,可约去 \(r_{1}r_{2} \cdots r_{\varphi (m)}\),即得 \(a ^ {\varphi (m)} \equiv 1 \pmod {m}\)

费马小定理:若 \(p\) 为素数,则 \(a ^ {p - 1} \equiv 1 \pmod {p}\)

证明:当 \(p\) 为素数 \((a, p) = 1\),由于 \(\varphi (m - 1) = m - 1\),带入欧拉定理可立即得到费马小定理。

线性同余方程

\((a, m) = d\),则一次同余方程:\(ax \equiv b \pmod {m}\),有解的充要条件是 \(d \mid b\)

设同余方程有解 \(x = c\),则 \(m \mid (ac - b)\),从而 \(d \mid (ac - b)\),但 \(d \mid a\),故 \(d \mid b\)

反过来,若 \(d \mid b\),则同余方程与 \(\frac {a}{d} x \equiv \frac {b}{d} \pmod {\frac {m}{d}}\) 同解,任取模 \(\frac {m} {d}\) 的一个完系 \(c_{1}, \cdots, c_{\frac {m}{d}}\),因 \((\frac {a}{d}, \frac {m}{d}) = 1\)\(\frac {a}{d}c_{1} - \frac {b}{d}, \cdots, \frac {a}{d}c_{\frac {m}{d}} - \frac {b}{d}\) 也是模 \(\frac {m}{d}\) 的完系,所以同余方程存在整数解,且形成模 \(\frac {m}{d}\) 的一个同余类。但 \(d \mid b\) 时,原同余方程(模 \(m\))恰有 \(d\) 个解。

int x, y;
int d = exgcd (a, p, x, y);

if (b % d) {
    res = -1;
} else {
    x *= (b / d);
    res = (x % (p / d) + (p / d)) % (p / d);
}

中国剩余定理

中国剩余定理:设 \(m_{1}, \cdots , m_{k}\) 是两两互素的正整数,则对于任意整数 \(b_{1}, \cdots ,b_{k}\),一次同余方程组 \(x \equiv b_{1} \pmod {m_{1}}, \cdots , x \equiv b_{k} \pmod {m_{k}}\) 必有解,且全部解是模 \(m_{1} \cdots m_{k}\) 的一个同余类。确切地说,同余方程组的解是 \(x \equiv M_{1}M_{1}^{-1}b_{1} + \cdots + M_{k}M_{k}^{-1}b_{k} \pmod {m_{1} \dots m_{k}}\)

其中 \(M_{i}\)\(M_{i}^{-1}\) \((1 \leq i \leq k)\) 由条件 \(m_{1} \cdots m_{k} \equiv M_{i}m_{i}, M_{i}M_{i}^{-1} \equiv 1 \pmod {m_{i}}\) 决定。因为 \((m_{i}, M_{i}) = 1\),故有整数 \(M_{i}^{-1}\),使得 \(M_{i}M_{i}^{-1} \equiv 1 \pmod {m_{i}}\)。对 \(j \neq i\),有 \(m_{j} \mid M_{i}\),因此数 \(d_{i} = M_{i}M_{i}^{-1}\),满足:\(d_{i} \equiv 1 \pmod {m_{i}}, d_{i} \equiv 0 \pmod {m_{j}}\) (对 \(j \neq i\))。

易于验证,上面的解的”叠加“ \(b_{1}d_{1} + \cdots + b_{k}d_{k}\) 满足同余方程组的解。

另一方面,如果 \(x, x^{\prime}\) 都是同余方程组的解,则 \(x \equiv x^{\prime} \pmod {m_{i}}, 1 \leq i \leq k\)。由 \(m_{1}, \cdots , m_{k}\) 两两互素知,\(x \equiv x^{\prime} \pmod {m_{1} \cdots m_{k}}\),因此同余方程组的解是模 \(m_{1} \cdots m_{k}\) 的一个同余类。

线性同余方程组

模数互质,使用中国剩余定理。

vector <int> A(n), B(n);
LL M = 1;
for (int i = 0; i < n; i ++ ) {
    cin >> A[i] >> B[i];
    M *= A[i];
}

LL res = 0;
for (int i = 0; i < n; i ++ ) {
    LL Mi = M / A[i];
    LL ti, x;
    exgcd (Mi, A[i], ti, x);
    res += B[i] * Mi * ti;
}

cout << (res % M + M) % M << "\n";

在模数不互质的情况下,设其中两个方程分别是 \(x \equiv a_{1} \pmod {m_{1}},x \equiv a_{2} \pmod {m_{2}}\)。转化为不定方程:\(x = m_{1}p + a_{1} = m_{2}q + a_{2}\),其中 \(p, q\) 是整数,则有 \(m_{1}p - m_{2}q = a_{2} - a_{2}\)。由裴蜀定理,当 \(a_{2} - a_{1}\) 不能被 \((m_{1}, m_{2})\) 整除时,无解;否则,扩展欧几里得定理得到一组可行解 \((p, q)\),则这两个方程组的解是 \(x \equiv b \pmod {M}\),其中 \(b = m_{1}p + a,M = [m_{1}, m_{2}]\)。多个方程两两合并。

LL res = 0, m1, a1;
cin >> m1 >> a1;

for (int i = 0; i < n - 1; i ++ ) {
    LL m2, a2;
    cin >> m2 >> a2;

    LL k1, k2;
    LL d = exgcd (m1, m2, k1, k2);

    if ((a2 - a1) % d) {
        res = -1;
    }

    k1 *= (a2 - a1) / d;
    k1 = (k1 % (m2 / d) + (m2 / d)) % (m2 / d);

    LL m = abs (m1 / d * m2);
    a1 = k1 * m1 + a1;
    m1 = m;
}

if (res != -1) {
    res = (a1 % m1 + m1) % m1;
}

cout << res << "\n";
posted @ 2022-06-29 16:05  Lucius7  阅读(693)  评论(3)    收藏  举报