中国剩余定理&扩展中国剩余定理 入门详解

本文详细介绍了中国剩余定理和扩展中国剩余定理,包括基本概念、解题方法、证明过程以及如何处理非互质情况。通过实例解析了同余方程组的求解,并给出了算法实现思路。

中国剩余定理

例题

  • 已知以下nnn同余方程(所有mim_imi互质):
  • x≡a1(mod  m1)x≡a_1(\mod m_1)xa1(modm1)
  • x≡a2(mod  m2)x≡a_2(\mod m_2)xa2(modm2)
  • x≡a3(mod  m3)x≡a_3(\mod m_3)xa3(modm3)
  • ……
  • x≡an(mod  mn)x≡a_n(\mod m_n)xan(modmn)
  • 求最小的xxx.

样例

n=3n=3n=3
x≡1(mod  3)x≡1(\mod 3)x1(mod3)
x≡2(mod  5)x≡2(\mod 5)x2(mod5)
x≡3(mod  7)x≡3(\mod 7)x3(mod7)

朴素解法

  • 先找出符合第一条的最小的xxx
  • 那么x=4x=4x=4.
  • 再看使它符合第二条,同时保证第一条成立,每次加上333
  • x=7x=7x=7时,成立,
  • 还要使它满足第三条,同时保证前两条成立,每次加上gcd(3,5)=15gcd(3,5)=15gcd(3,5)=15
  • x=52x=52x=52时,成立,
  • 所以最终答案就是x=52x=52x=52
  • 这样做非常慢,如果式子太多效率是非常低的。

中国剩余定理

  • 先令M=ΠmiM=\Pi{m_i}M=Πmici=Mmic_i=\frac{M}{m_i}ci=miMci−1c_i^{-1}ci1表示cic_ici在模mim_imi意义下的乘法逆元,
  • 则答案Ans=∑ai∗ci∗ci−1mod  MAns=\sum a_i*c_i*c_i^{-1} \mod MAns=aicici1modM

证明

  • 只需要证明方程组中每条式子成立即可,
  • 也就是说,证明任意一个iii,有Ans≡ai(mod  mi)Ans≡a_i(\mod m_i)Ansai(modmi)
  • i≠ji\neq ji=j时,有cimod  mj=0c_i\mod m_j=0cimodmj=0
  • 所以Ans≡∑aj∗cj∗cj−1≡ai∗ci∗ci−1≡ai(mod  mi)Ans≡\sum a_j*c_j*c_j^{-1} ≡a_i*c_i*c_i^{-1}≡a_i(\mod m_i)Ansajcjcj1aicici1ai(modmi)
  • 即该定理成立。

扩展中国剩余定理

例题

  • 已知以下nnn同余方程(所有mim_imi互质的条件不存在了):
  • x≡a1(mod  m1)x≡a_1(\mod m_1)xa1(modm1)
  • x≡a2(mod  m2)x≡a_2(\mod m_2)xa2(modm2)
  • x≡a3(mod  m3)x≡a_3(\mod m_3)xa3(modm3)
  • ……
  • x≡an(mod  mn)x≡a_n(\mod m_n)xan(modmn)
  • 求最小的xxx.

分析

  • 朴素解法仍然适用。
  • 但如果用中国剩余定理的话,不保证互质的情况下,乘法逆元无法求得,
  • 此时需要用别的方法。

扩展中国剩余定理

  • 这里直接用一般的形式来讲解。
  • 先使前两条式子成立,
  • x≡a1(mod  m1)x≡a_1(\mod m_1)xa1(modm1)
  • x≡a2(mod  m2)x≡a_2(\mod m_2)xa2(modm2)
  • 可以变形为:
  • x=m1∗y1+a1x=m_1*y_1+a_1x=m1y1+a1
  • x=m2∗y2+a2x=m_2*y_2+a_2x=m2y2+a2
  • m1∗y1+a1=m2∗y2+a2m_1*y_1+a_1=m_2*y_2+a_2m1y1+a1=m2y2+a2
  • 变形得到m1∗y1−m2∗y2=a2−a1m_1*y_1-m_2*y_2=a_2-a_1m1y1m2y2=a2a1
  • 式子中的y1y_1y1y2y_2y2是未知的,显然可以用扩展欧几里德来求解!
  • 当然要判断gcd(m1,m2)gcd(m_1,m_2)gcd(m1,m2)是否能被a2−a1a_2-a_1a2a1整除,如果不行则是无解的。
  • y1y_1y1y2y_2y2求出以后,都乘上(a2−a1)/gcd(m1,m2)(a_2-a_1)/gcd(m_1,m_2)(a2a1)/gcd(m1,m2)
  • 求出当前的解x′x'x.
  • 接着当前的解可以转换成一条新的方程式:
  • x=x′(mod  lcm(m1,m2))x=x'(\mod lcm(m_1,m_2))x=x(modlcm(m1,m2))
  • 这样继续和下一条方程式合并成一条新的方程式,
  • 当只剩一条方程时,x′x'x就是最终的答案。

代码

#include<cstdio>
#include<cstring>
using namespace std;
#define LL long long
LL a[11],m[11];
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,x,y);
	LL t=x;
	x=y;
	y=t-a/b*y;
	return d;
}
int main()
{
	int n,i;
	scanf("%d",&n);
	for(i=1;i<=n;i++) scanf("%lld%lld",&m[i],&a[i]);
	LL A=a[1],M=m[1];
	for(i=2;i<=n;i++)
	{
		LL x=0,y=0;
		LL l=a[i]-A;
		LL d=exgcd(M,m[i],x,y);
		if(l%d>0)
		{
			printf("-1");
			return 0;
		}
		x*=l/d;
		x=(x%m[i]+m[i])%m[i];
		A+=M*x;
		M=M/d*m[i];
		A%=M;
	}
	printf("%lld",A);
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值