中国剩余定理学习笔记
CRT
求一个最小的 \(x\) 使得
\(\begin{cases} x \equiv a_1\ ({\rm mod}\ b_1) \\ x\equiv a_2\ ({\rm mod}\ b_2) \\ ... \\ x \equiv a_n\ ({\rm mod}\ b_n)\end{cases}\)
其中 \(b_1, b_2, ..., b_n\) 互质
考虑将 \(x\) 拆成 \(x_1 + x_2 + ... + x_n\)
使 \(x_1\) 满足:
- 它是 \(b_2, b_3, ..., b_n\) 的倍数
- \(x_1 \equiv a_1 (\text{mod }b_1)\)
使 \(x_2\) 满足:
- 它是 \(b_1, b_3, b_4, ..., b_n\) 的倍数
- \(x_2 \equiv a_2 (\text{mod }b_2)\)
以此类推
又因为 \(b\) 是互质的 所以任何几个 \(b\) 的 lcm 直接就是它们的乘积
那么显然有 $x = \sum\limits_{i = 1}^n x_i \mod \prod\limits_{i = 1}^n b_i $
然后我们考虑怎么求 \(x_i\)
首先肯定要求出 \(pai = \prod b_i\)
然后有一个比较显然的结论 设 \(x \equiv 1 (\text{mod } mod)\)
则 \(a x \equiv a (\text{mod } mod)\)
所以我们要先求出一个 \(x_i' \equiv 1 (\text{mod } b_i)\)
以 \(x_1\) 为例 首先 \(x_1'\) 一定是 \(pai / b_1\) 的整数倍
一个很暴力的想法就是枚举这个倍数 直到余数为 \(1\)
我们设这个倍数为 \(k\) 发现有 \(k \times pai / b_1 \equiv 1 (\text{mod }b_1)\)
我们发现实际上 \(k\) 就是 \(pai / b_1\) 在模 \(b_1\) 意义下的逆元
- 注意 \(b_i\) 不一定为质数 所以要用扩欧求逆元 并且记得判负
从中也可以看出为什么要求所以 \(b\) 互质
因为实质上你的扩欧方程是 \(pai / b_i \times k + b_i \times y = 1\)
根据裴蜀定理 只有 \(\gcd (pai / b_i, b_i) = 1\) 即 \(b_i\) 与其他所有 \(b\) 都互质的时候才有解
- 注意求出来 \(k\) 之后我们还要再乘上 \(a_i\) 并且这个过程需要开快速乘
洛谷板子题:P3868 [TJOI2009] 猜数字
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 11;
ll a[N], b[N];
ll pai = 1;
int k;
ll ans;
ll ksc(ll x, ll y) {
ll ret = 0;
while (y) {
if (y & 1) ret = (ret + x) % pai;
x = (x + x) % pai;
y >>= 1;
}
return ret;
}
void exgcd(ll a, ll b, ll &x, ll &y) {
if (b == 0) {
x = 1;
y = 0;
return;
}
exgcd(b, a % b, x, y);
ll z = x;
x = y;
y = z - (a / b) * y;
}
int main() {
scanf("%d", &k);
for (int i = 1; i <= k; ++i) scanf("%lld", &a[i]);
for (int i = 1; i <= k; ++i) {
scanf("%lld", &b[i]);
pai *= b[i];
}
for (int i = 1; i <= k; ++i) {
ll x, y;
exgcd(pai / b[i], b[i], x, y);
x = (x % b[i] + b[i]) % b[i];
a[i] = (a[i] % b[i] + b[i]) % b[i];
ans = (ans + ksc(pai / b[i] * x, a[i])) % pai;
}
printf("%lld", ans);
return 0;
}
exCRT
求一个最小的 \(x\) 使得
\(\begin{cases} x \equiv a_1\ ({\rm mod}\ b_1) \\ x\equiv a_2\ ({\rm mod}\ b_2) \\ ... \\ x \equiv a_n\ ({\rm mod}\ b_n)\end{cases}\)
不保证 \(b_1, b_2, ..., b_n\) 互质
咕了 有时间再填