中国剩余定理解法

问题表述
 
《孙子算经》卷下第二十六问:“今有物,不知其数。三、三数之,剩二;五、五数之,剩三;七、七数之,剩二。问物几何?答曰:二十三。”

即 x%3=2;x%5=3;x%7=2;  》》  x=23+3*5*7*k

表述成定理为:
给m个两两互质的数,其乘积为P,若已知x<P,且知x与这m个数的模,则x唯一确定。

以m=2为例,设为a,b,令x=1~a*b;
x mod a 的结果为 (0,1,...,a-1) 的循环;
x mod b 的结果为 (0,1,...,b-1) 的循环;
则(x%a, x%b)的循环周期为P=a*b, 在P范围内,是唯一确定的。
 
 
问题求解
m=3,分别为a,b,c,如何求x?
brute-force:
     求出P内满足条件 i (x%ai=ci) 的x的集合,求交。
clever:
     构造出一个满足条件的x,不必小于P,x%P即为所求。具体的,构造t1为ab的倍数,且模c等于x模c,同理构造出t2,t3,则 x=(t1+t2+t3)%P。

这引出了下一个问题:a*x % b = c ,求x?
     事实上,只有当a与b互质,方程有解;因为其等价于 X=a*x,X%a=0,X%b=c,由中国剩余定理可知其有解。if (a*x)% b= 1, (a*c*x)%b = c,因此也等价于求 (a*x)% b= 1 。
     即求解 a的多少倍 - b的多少倍 = 1,用扩展的辗转相除法。
     如a=5,b=7:
          7/5 = 1 ...2,(5,7) 的系数为 (1,1),剩下 5,2
          5/2 = 2 ...1,(5,2) 的系数为 (1,2),于是(5,7)的系数为(3,2)
          5*3 - 7*2 = 1,求得 x = 3。
     该扩展辗转相除法还是相当精妙的!

     若 a和b的最大公约数d不为1,则只能求解 a*x % b = d 。
 
参考:Matrix67大牛的博文 ---“跨越千年的RSA算法
 
 
代码实现
 
python写的代码,从上述思路到实现还是有一定距离的,^ ^
# solve a*x % b = c ;
# a and b are co-prime ;
# solve it equals to a*x % b = 1 ,
# cause if (a*x)% b= 1, (a*c*x)%b = c

def example():
    a = 115
    b = 367
    c = 2
    for i in range(1,20):
        print (a*i%b)

# GCD(a,b) should be 1
def extra_divide(a,b,c):
    if not c<b:
        print 'b should be greater than c'
        return -1
    # assume a > b
    aa = a
    bb = b
    exchanged = False
    if a<b:
        exchanged = True
        t = a
        a = b
        b = t
    
    rec_array = []
    
    r = 0
    while r!=1:
        r = a%b
        d = a/b
        rec_array.append( 1 )
        rec_array.append( d )

        a = b
        b = r

    #print rec_array

    # this is the most important part, take 25,7 for example
    # 25 % 7, 7 % 4, 4 % 3
    #  1   3, 1   1, 1   1;  one 3 equals one 7 and one 4, so
    #  1   3, 1   2;         two 4 equals two 25 and six 7, so
    #  2   7;
    
    
    for i in range(0,len(rec_array)-2,2):
        j = len(rec_array) - i - 1
        rec_array[j-2] *= rec_array[j]
        rec_array[j-3] *= rec_array[j]
        rec_array[j-2] += rec_array[j-1]
    k1 = rec_array[0]
    k2 = rec_array[1]

    if exchanged:
        t = k1
        k1 = k2
        k2 = t
    
    # we want ax%b=1, now b%(ax)=1, so play a magic here
    # k1*a + 1 = k2*b, also b*a = a*b, take a difference
    # we get (b-k1)*a -1 = (a-k2)*b, bingo!
    if aa*k1 < bb*k2:
        k1 = bb-k1
        k2 = aa-k2

    print 'x='+str(k1), 'a*x='+str(k1*aa), 'b*y='+str(k2*bb)

## test
extra_divide(7,5,1)
extra_divide(25,7,1)
extra_divide(115,367,1)
extra_divide(367,115,1)
extra_divide(128,367,1)




<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]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值