目录

一、引入:古人奇妙的问题与解法。

二、步入正题:什么是中国剩余定理?

1.如何解决

(1)第一步:分解

(2)第二步:计算

(3)第三步:合并

(4)最终求出结果

2.深入中国剩余定理

3.一道合适的自测题目

三、扩展算法:扩展中国剩余定理(大数翻倍法)。

1.说出我的扩展的理由

2.定理原理:主要合并

3.附上代码:写的不好QAQ

四、最后 


一、引入:古人奇妙的问题与解法。

 有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二。问物几何?——《孙子算经》(所以中国剩余定理也称孙子定理)

        翻译过来就是 “有一样东西不知道有多少,三个三个数剩二个,五个五个数剩三个,七个七个数剩二个。问有多少东西?”,且这个问题问最小值若将它转化为符号与数字,也就是一组同余方程,如下。

 \left\{\begin{matrix} x\equiv 2 (\mod 3)\\ x\equiv 3 (\mod 5)\\ x\equiv 2 (\mod 7) \end{matrix}\right.

        注:我们这里设x为东西的数量,下文也会提及。

二、步入正题:什么是中国剩余定理?

1.如何解决
(1)第一步:分解

        这个问题我们可以拆解一下,变为……

  • “三个三个数剩一个(1),五个五个数一个不剩(0),七个七个数同样一个不剩(0)。”
  • “三个三个数一个不剩(0),五个五个数剩一个(1),七个七个数同样一个不剩(0)。”
  • “三个三个数一个不剩(0),五个五个数同样一个不剩(0),七个七个数剩一个(1)。”
(2)第二步:计算

        让我们先来解三个分解问题……以第一题为例,怎么解呢?以x与0同余为突破口,已知x为5和7的倍数也就是lcm(5,7)=35(最小公倍数)的倍数所以我们设x=35y,解同余方程35y \equiv 1 (\mod3),首先左侧35y对3取余得2y,即为2y\equiv 1(\mod 3)再次变换为y\equiv \frac{1}{2}(\mod 3),显然还需要求\frac{1}{2}的逆元即1 \times 2^{3-2}=2,即x=70

        其余以此类推,同理第二题为21,第三题为15。

(3)第三步:合并

        有点意思~我们只需要按照原来的“三个三个数剩二个,五个五个数剩三个,七个七个数剩二个”变为2\times 70+3\times 21+2\times 15=233(上文数值),但这数也未免太大了,所以还需要233\mod 105=23,但为什么对105取余?那是因为lcm(3,5,7)=105,通过取模来去掉不需要的部分(停下思考ing)。

(4)最终求出结果

        结果为23,这就是中国剩余定理能解决的问题——解决求最小满足上文类型同余方程的定理。

        注:相信你已经了解了许多,这里只是一些定理,若了解深刻,可自行跳过。

2.深入中国剩余定理

\left\{\begin{matrix} x\equiv a_1 (\mod m_1)\\ x\equiv a_2 (\mod m_2)\\......\\x\equiv a_n (\mod m_n) \end{matrix}\right. 

        这,是一组同余方程,它共有n个,且m_1m_n两两互质用上文方法,一个一个开始“孤立”。

\left\{\begin{matrix} x\equiv 0(\mod m_1)\\......\\x\equiv 1(\mod m_i)\\......\\x\equiv 0 (\mod m_n) \end{matrix}\right. 

        这样整个方程组只剩一个同余于1,其他为0,我们设N为所有m_i的乘积,还记得y吗?我们分解成许多y_i,现在我们通过式子将y_i的值写出来,如下。

        注:请谨慎辨别下方算式,(举个例子)当a在模p意义下且ap不互质时,a没有逆元!

\frac{N}{m_i}y_i\equiv 1(\mod m_i)\\\\ 1\div \frac{N}{m_i}\mod m_i=\frac{N^{\varphi (m_i)-1}}{m_i^{\varphi (m_i)-1}}\\\\ y_i=\frac{N^{\varphi (m_i)-1}}{m_i^{\varphi (m_i)-1}}\mod m_i

        有了y_i ,便可求得x=\sum_{i=1}^{n}\frac{a_iy_iN}{m_i}\mod N,好问题又来了,为什么没有lcm?那是因为上文说过两两互质。

3.一道合适的自测题目

        在洛谷中有一道非常合适的模板题,传送门在这,but我只有扩展中国剩余定理的的代码,不过通用,继续往下看吧。

三、扩展算法:扩展中国剩余定理(大数翻倍法)。

1.说出我的扩展的理由

        首先我觉得很赞,首先他可以免除所有m_i必须两两互质的悲伤事情。其次代码也很简单易懂,更适合编程宝宝体质。

2.定理原理:主要合并

        首先有x\equiv a_1(\mod m_1)x\equiv a_2(\mod m_2)两个同余方程,将其可合并为xa_1+nm_1(此na_1+km_1 \not\equiv a_2 (\mod m_2)k的最小值)或a_2+nm_2(此na_2+km_2 \not\equiv a_1 (\mod m_1)k的最小值)在模lcm(m_1,m_2)的意义下。

        注:后面就是代码了,请放心食用😀。

3.附上代码:写的不好QAQ

        而在洛谷中还有一道非常合适的模板题,传送门在这。代码如下……

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) a/gcd(a,b)*b
void merge(ll &a,ll &pa,ll b,ll pb){
	if(pa<pb)swap(pa,pb),swap(a,b);//小小的优化:交换,后面循环能更短。
	ll l=lcm(pa,pb);//提前计算也是一个小小优化,让循环更短。
	while(a<=l&&a%pb!=b)a+=pa;
	if(a>l)a=0,pa=1;//在加一个特判前后呼应。
    else pa=l;
}
ll n,x,p,sumx,sump=1;//x≡sumx(mod sump),即为最终合并的结果。
int main(){
	scanf("%lld",&n);
	for(ll i=1;i<=n;i++){
		scanf("%lld%lld",&p,&x);
		x%=p;
		merge(sumx,sump,x,p);
	}
	printf("%lld",sumx);
} 

        如果去掉优化即为……

void merge(ll &a,ll &pa,ll b,ll pb){
	while(a%pb!=b)a+=pa;
    pa=lcm(pa,pb);
}

        提一嘴,这一道题是道洛谷紫题,同样也是我的第一道紫题。 

四、最后 

        中国文化博大精深,非常适合中国宝宝体质

Logo

欢迎加入西安开发者社区!我们致力于为西安地区的开发者提供学习、合作和成长的机会。参与我们的活动,与专家分享最新技术趋势,解决挑战,探索创新。加入我们,共同打造技术社区!

更多推荐