CRT 小记

\[ \]

中国剩余定理(CRT)

问题

给定 \(n\) 对 \(a_i, b_i\)。求最小的 \(x\),使得 \(\forall i \in [1, n]\),均有 \(x \equiv {b_i} \pmod {a_i}\)。

\(a_{1..n}\) 两两互质。

为方便实现,保证 \(\prod a_i \le 10^{18}\)。

算法概要

我们希望用类似于插值的做法,即在使第 \(i\) 个方程组合法时,不改变其它方程组的结果。

令 \(M = \prod a_i\),则处理第 \(i\) 个方程组时,令 \(x \gets x + t\frac{M}{a_i}\),则一定可以取到 \(t\) 使 \(x\) 满足 \(1\sim i\) 所有方程组。

在这个算法中,当 \(t\) 取的是最小正整数时,我们不会使 \(x \ge M\)。若 \(x \ge M\),可以 \(x \gets x \bmod M\)。

使用 exgcd 求逆,时间复杂度可做到 \(n \log V\)。

核心代码
for (int i = 1; i <= n; i++) {
    int p = mul / a[i];
    int x, y;
    exgcd(p, a[i], x, y);
    if (x < 0)
        x += a[i];
    ans += b[i] * p * x;
}

扩展中国剩余定理(EXCRT)

问题

给定 \(n\) 对 \(a_i, b_i\)。求最小的 \(x\),使得 \(\forall i \in [1, n]\),均有 \(x \equiv {b_i} \pmod {a_i}\)。

不保证 \(a_{1..n}\) 两两互质。

为方便实现,保证 \(\mathop{\operatorname{lcm}} a_i \le 10^{18}\)。

算法概要

刚刚的做法无法行通了,因为可能逆元不存在。考虑一个一个方程组来满足。

在 \(1 \sim i\) 的方程中,合法解集为 \(p+Mx\)。需要让其在模 \(a_{i+1}\) 意义下余数为 \(b_{i+1}\)。即找到 \(x, y\) 使 \(p+Mx = b_{i+1} + a_{i+1}y\)。这个可以使用 exgcd 解决。

更通用地,可以先把每个方程的解集解出来再合并。

时间复杂度还是 \(O(n \log V)\)。

核心代码
ll p = a[1], q = b[1];
for(int i = 2; i <= n; ++i) {
	ll g = exgcd(p, a[i], x, y);
	if((b[i] - q) % g != 0)
		cout << "-1\n", exit(0);
	x = mul(x, (b[i] - q) / g, a[i] / g);
	q = p * x + q;
	p = p / g * a[i];
	q = (q % p + p) % p;
}

\(\color{green}\text{P4774 [NOI2018] 屠龙勇士}\)

Problem

给长为 \(n\) 的数组 \(a, p, b\),和一个长为 \(m\) 的数组 \(c\)。

初始拥有 \(m\) 把剑,攻击力 \(c_{1..m}\)。有 \(n\) 个怪物,以 \(1 \sim n\) 的顺序进行战斗。每一次开始战斗时,会选择当前拥有的,攻击力不超过怪物生命值 \(a_i\) 中攻击力最大的剑,若不存在则使用攻击力最低的剑作为武器。不妨令 \(\operatorname{ATK}\) 表示这个武器的攻击力。

你需要选定一个参数 \(x\),每一轮会攻击 \(x\) 次,即造成 \(x \times \operatorname{ATK}\) 伤害。之后,怪物会不断地回复,第 \(i\) 个怪物的恢复能力为 \(p_i\),若怪物的生命值变为 \(0\),则怪物死亡。(注意:在 \(n\) 局游戏中,\(x\) 是固定的)。然后你将损失这把剑并获得一把攻击力为 \(b_i\) 的剑。

问把 \(x\) 设置成多少时,攻击次数最少。

\(n, m \le 10^5\),\(a_i \le 10^{12}\),\(\mathop{\operatorname{lcm}} p_i \le 10^{12}\),所有剑的攻击力均 \(\le 10^6\)。

Sol

对于每个怪物,攻击的剑是确定的。

那么就变为了求一个 \(x\),使:

\[\left\{\begin{matrix} x t_1 \equiv {a_1} \pmod {p_1} \\ x t_2 \equiv {a_2} \pmod {p_2} \\ x t_3 \equiv {a_3} \pmod {p_3} \\ \vdots \\ x t_n \equiv {a_n} \pmod {p_n} \\ \end{matrix}\right. \]

均成立。需要注意,这里 \(x\) 需要使 \(xt_i \ge a_i\),即 \(x \ge \max \frac{a_i}{t_i}\),有一个下界。

然后这就是 EXCRT 的板子了啊。还是一样的嘛,一个一个合并。先解出每个方程对应的 \(x\) 的解集 \(k_ix + b_i\)。然后合并就行了。

时间复杂度 \(O(n \log V)\)。

posted @ 2026-01-05 09:13  Pengzt  阅读(21)  评论(0)    收藏  举报