中国剩余定理学习笔记

中国剩余定理

作用

中国剩余定理 (Chinese Remainder Theorem, CRT),也称孙子定理,是用来求解线性同余方程组,即如下面的方程组:

\[\begin{cases} x \equiv &a_1\ ({\rm mod}\ p_1) \\ x \equiv &a_2\ ({\rm mod}\ p_2) \\ & \vdots \\ x \equiv &a_n\ ({\rm mod}\ p_n) \end{cases} \]

这个定理可以在 $O(n \log p) $ 的时间内求解这个方程组的最小整数解,要求 \(p_1,p_2,\dots p_n\) 两两互质。

定理

这个定理告诉我们要怎么求解 \(x\) 的最小正整数值。

实现步骤:

  1. \(M = \displaystyle\prod_{1 \le i \le n} p_i\), 求出 \(M\)

  2. \(m_i = \frac{M}{p_i}\) , \(t_i = m_i^{-1} \pmod {p_i}\) ,求出每个 \(m_i\)

  3. \(x\) 的一个解是 \(\displaystyle\sum_{1\le i\le n}a_i\times m_i \times t_i\) ,最小的正整数解就是 \(x \bmod M\)

证明非常简单,对于任意一个方程 \(x \equiv a_k \pmod {p_k}\) ,除了 \(k\) 以外的所有 \(a_i \times m_i \times m_i^{-1}\) 整除 \(p_k\) ,而 \(a_k \times m_k \times m_k^{-1}\) 在模 \(p_k\) 意义下变为:

\[a_k \times m_k \times m_k^{-1} \equiv a_k \pmod {p_k} \]

得证。

总的时间复杂度是 \(O(n \log p)\)

code

int n;
typedef long long ll;
ll p[15] = {0}, a[15] = {0};
ll phi(ll x) {
	ll ans = x;
	for (ll d = 2; x > 1; d++) {
		if (d * d > x)
			return ans / x * (x - 1);
		if (x % d == 0) {
			ans = ans / d * (d - 1);
			while (x % d == 0)
				x /= d;
		}
	}
	return ans;
}
ll fpow(ll a, ll b, ll p) {
	if (b == 0)
		return 1ll;
	ll ans = fpow(a, b / 2, p);
	ans = ans * ans % p;
	if (b % 2 == 1)
		ans = ans * a % p;
	return ans;
}
ll CRT() {
	ll mul = 1;
	for (int i = 1; i <= n; i++)
		mul *= p[i];
	ll ans = 0;
	for (int i = 1; i <= n; i++)
		ans += a[i] * fpow(mul / p[i], phi(p[i]) - 1, p[i]) % mul * (mul / p[i]) % mul, ans %= mul;
	return ans % mul;
}

扩展中国剩余定理(exCRT)

考虑 CRT 的求解过程,关键的是求逆元,但是如果模数两两不互质就不存在逆元。所以 CRT 要求模数两两互质,而 exCRT 就可以处理两两不互质的情况。

我们先考虑两个方程的情况:

\[\begin{cases} x \equiv a \pmod n\\ x \equiv b \pmod m \end{cases} \]

显然,如果这个方程有解,那么一定存在两个整数 \(p, q\) 使得 \(x = pn + a = qm + b\)

改变一下形式得到:\(pn - qm=b - a\)

这样就变成了二元一次方程的求解,根据裴蜀定理,如果 \(\gcd(n,m) \not | b - a\),则方程无解。

否则,我们可以用 exgcd 找到一组解 \((p_0, q_0)\),我们就可以得到原方程的通解:

\[\begin{cases} p = p_0 + \frac{m}{\gcd(n,m)}t\\ q = q_0 + \frac{n}{\gcd(n,m)}t\\ \end{cases} \]

将通解代入原来的式子就能得到:

\[\begin{aligned} x &=n \times(p_0 + \frac{m}{\gcd(n,m)}t)+a\\ &=(np_0+a)+\frac{nm}{\gcd(n,m)}t\\ &=(np_0+a)+\operatorname{lcm}(n,m)t \end{aligned} \]

\(np_0+a\) 记作 \(c\), 我们可以将 \(x\) 表示为一个同余方程的解,也就是:

\[x \equiv c \pmod {\operatorname{lcm}(n,m)} \]

这样我们就得到了一个新的同余方程。

如果还有第三个方程,就用这个方程与其合并,和上面一样,最后将所有方程都合并后就能得到答案。

一些题目

题目1:\(n\) 个人站成一圈,顺时针按照 \(1 \sim k\) 报数,每次报到 \(k\) 的人出局。已知出去顺序,求最小的 \(k\)\(n \le 20\)。(P5944 [POI2002] 出圈游戏

思路:

我们考虑第一个出局的人是 \(x\),则说明 \(k \equiv x \pmod n\)

以此类推我们可以得到 \(n\) 个方程:

\[\begin{cases} k \equiv &a_1\ ({\rm mod}\ n) \\ k \equiv &a_2\ ({\rm mod}\ n-1) \\ & \vdots \\ k \equiv &a_n\ ({\rm mod}\ 1) \end{cases} \]

然后用 exCRT 求解即可。

题目2: 给定 \(n,G (n,G \le 10^9)\),求:

\[G^{\sum_{k|n}\binom{n}{k}} \bmod 999911659 \]

的值。(P2480 [SDOI2010] 古代猪文

思路:

经典题目。

首先,由于 \(999911659\) 是个质数,根据费马小定理,\(G^b \equiv G^{b \bmod 999911658}\)

所以我们只要求出这个值就能用快速幂求出答案。

现在考虑如何求 \(\sum_{k|n}\binom{n}{k} \bmod 999911658\)

首先,我们可以枚举 \(k\), 复杂度 \(O(\sqrt{n})\)

现在考虑如何求 \(\binom{n}{k} \bmod 999911658\)

由于模数不是个质数,而且 \(n\) 太大,没法预处理逆元。

但是我们发现 \(999911658 = 2 \times 3 \times 4679 \times 35617\),刚好是几个质数的乘积。

所以我们可以对每个质数分别求出对其取模的值,然后用 CRT 将这些同余方程合并起来。

现在考虑如何求 \(\binom{n}{k} \pmod p\),(\(p\) 是质数)。

一种方法是卢卡斯定理直接求,比较简单,时间复杂度 \(O(\log n)\)

当然还有一种方法可以不用卢卡斯定理。

众所周知,\(\binom{n}{k}=\frac{n!}{k!(n-k)!}\)

我们首先计算出 \(n!\)\(k!\)\((n-k)!\) 中分别含有 \(p\) 的几次方。

这个可以通过经典结论:\(n!\)\(p\) 的次数为 \(\sum_{i=0}\lfloor\frac{n}{p^i}\rfloor\)

然后我们看一下 \(n!\)\(k!(n-k)!\) 是否次数相等,如果不相等,说明是 \(p\) 的倍数,答案就是 \(0\)

否则,我们考虑求出这三个阶乘再去掉所有的 \(p\) 后在 \(\bmod p\) 意义下的值和逆元,就可以求出答案。

不妨设 \(f(n)\) 表示 \(n!\) 去掉所有 \(p\) 后对 \(p\) 取模的值。

\(n < p\) 是,\(f(n)=n! \bmod p\)

否则,\(f(n)=f(\lfloor \frac{n}{p}\rfloor) \times (-1)^{\lfloor \frac{n}{p}\rfloor} \times (n \bmod p)! \pmod p\)

感性理解一下,我们将 \(1 \sim n\) 分成若干段,每一段都是 \([p+1 , (k+1)p]\)

首先,末尾会有一些剩下,在模 \(p\) 意义下就是 \((n \bmod p)!\),所以要乘上这个东西。

再看每一段,去掉每段最后那个 \(p\) 的倍数,那么在模 \(p\) 意义下乘起来就是 \((p-1)!\),根据威尔逊定理,\((p-1)! \equiv 1 \pmod p\),所以我们需要乘上 \((-1)^{\lfloor \frac{n}{p}\rfloor}\)

再看 \(p\) 的倍数,将 \(p\) 去掉后就是 \(1,2,\dots,\lfloor \frac{n}{p}\rfloor\),于是这就成了一个子问题,递归求解即可。

时间复杂度是 \(O(\log n)\) 的,和卢卡斯定理一样。

然后就能做出这道题了。

posted @ 2022-12-04 10:19  rlc202204  阅读(67)  评论(0编辑  收藏  举报