中国剩余定理

概述

  中国剩余定理(CRT),又称孙子定理,其典型例题为著名的“韩信点兵”。

求解类型

中国剩余定理所能求解的问题如下:

给定同余方程组:
{ x ≡ a 1 ( m o d   m 1 ) x ≡ a 2 ( m o d   m 2 ) x ≡ a 3 ( m o d   m 3 ) ⋮ x ≡ a n ( m o d   m n ) \begin{cases} x \equiv a_1(mod\ m_1) \\ x\equiv a_2(mod\ m_2) \\ x\equiv a_3(mod\ m_3) \\ \vdots \\ x\equiv a_n(mod\ m_n) \end{cases} xa1(mod m1)xa2(mod m2)xa3(mod m3)xan(mod mn)
求解 x x x

  在这 n n n个式子中,所有的 m i ( i ∈ [ 1 , n ] ) m_i(i\in [1,n]) mi(i[1,n])都关于其他的 m j ( j ∈ [ 1 , n ] ) m_j(j\in [1, n]) mj(j[1,n])互质。
  对于该式,普通算法是难以快速求解的,所以一般会使用CRT或exCRT求解。

推导过程

  CRT的思路其实是利用构造的方法求出一个特解 x 0 x_0 x0 ,再由特解推出其他解。

  首先,对于一个同余式 x ≡ a i ( m o d   m i ) x\equiv a_i(mod\ m_i) xai(mod mi)而言,它能用扩展欧几里得算法求解得到一组特解 x 0 x_0 x0 ,且通解式为 x = x 0 + k × m x = x_0 +k\times m x=x0+k×m 其中 m m m 为模数。所以当我们算出第一个同余式的解时,我们就可以利用通解式算出满足其他同余式的解。

  可以想到,假如设 M = m 1 × m 2 × m 3 × ⋯ × m n M=m_1\times m_2\times m_3\times \cdots\times m_n M=m1×m2×m3××mn M i = M ÷ m i M_i = M\div m_i Mi=M÷mi

  那么,对于任意的 M i M_i Mi 而言,它一定只模 m i m_i mi 不为0,而对于其它的 m j ( j ≠ i ) m_j(j\not = i) mj(j=i) 而言,其模数一定为0。所以,我们可以求常出 M i M_i Mi 关于 m i m_i mi 的逆元 i n v i inv_i invi 。这样的话,对任意一组同余式而言一定存在一组特解 x 0 x_0 x0 可以表示为 x 0 = a i × M i × i n v i x_0 = a_i\times M_i\times inv_i x0=ai×Mi×invi

  同时,由于 M i m o d    m i − 1 = 0 M_i \mod m_{i - 1}=0 Mimodmi1=0 ,所以 a i × M i × t i a_i\times M_i \times t_i ai×Mi×ti 一定是 m i − 1 m_{i - 1} mi1 的倍数,所以如果 x i − 1 x_{i - 1} xi1 是第 i − 1 i - 1 i1 个同余式的解,那么 x i − 1 + a i × M i × t i x_{i-1}+a_i\times M_i \times t_i xi1+ai×Mi×ti一定是第 i − 1 i - 1 i1个同余式的解。

  由于 M i = M i + 1 × m i + 1 ÷ m i M_i = M_{i + 1} \times m_{i+1}\div m_{i} Mi=Mi+1×mi+1÷mi,所以 m i + 1 m_{i+1} mi+1 M i M_{i} Mi的倍数,如果从第一个同余式推出来的话,那么 x i − 1 + a i × M i × t i x_{i-1}+a_i\times M_i \times t_i xi1+ai×Mi×ti一定是第 i i i个式子的解。所以我们可以推导出公式:
x = ∑ i = 1 n a i M i t i x=\sum_{i = 1}^n a_iM_it_i x=i=1naiMiti
   x x x即为同余式解。

  对于此代码,我们可以用扩展欧几里得算法求逆元,这样的话实际代码难度不大。

code

int A[Size] , m[Size] , M[Size] , M1 , x , y , n , ans;
void exgcd(int n , int m)//扩展欧几里得
{
	if(m == 0)
	{
		x = 1;
		y = 0;
		return ;
	}
	exgcd(m , n % m);
	int z = x;
	x = y;
	y = z - y * (n / m);
	return ;
}

int CRT()
{
	for(int i = 0 ; i < n ; i ++)
	{
		M1 *= m[i];
	}
	for(int i = 0 ; i < n ; i ++)
	{
		M[i] = M1 / m[i];
		exgcd(M[i] , m[i]);
		ans += A[i] * x * M[i] % M1;
		ans %= M1;
	}
	return (ans + M1) % M1;//求最小非负整数解
}
通解

  我们可以发现,因为 M = ∏ i = 1 n m i M = \prod_{i = 1}^{n} m_i M=i=1nmi。所以,当且仅当特解 x 0 x_0 x0乘上 M M M的倍数时,对同余式没有影响。由此可得通解式 x = x 0 + k × M ( k ∈ Z ) x = x_0+k\times M(k\in Z) x=x0+k×M(kZ)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值