中国剩余定理


中国剩余定理

有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二。问物几何?即,一个整数除以三余二,除以五余三,除以七余二,求这个整数。

《孙子算经》中首次提到了同余方程组问题,以及以上具体问题的解法,因此在中文数学文献中也会将中国剩余定理称为孙子定理。

换句话说:“一个正整数除以3余2,除于5余3,除于7余2,求这个正整数是几?”

基本解法:

1)先找到除以3余2,除于7余2的数是那些。经过分析得到满足要求的数是21的倍数加2。

       2,23,44,65,96,107,........

2)在上述结果中继续寻找除以5余3的数。

3)满足上述要求的正整数是:23,128,233,338

这里 128-23=105  正好是[3,5,7]的最小公倍数

古人的解法:

先找5和7的公倍数中除以3余1的数:70

再找3和7的公倍数中除以5余1的数:21

再找3和5的公倍数中除以7余1的数:15

70*2+21*3+15*2=233

233-105=128

128-105=23

所以这个正整数最小是23.

 

先考虑问题的分解:

问题1:计算一个整数 [公式] ,使得它满足除以3余2、除以5余3、除以7余2。

如果能够找到三个整数 [公式] ,使得:

[公式] 除以3余2、除以5余0、除以7余0;

[公式] 除以3余0、除以5余3、除以7余0;

[公式] 除以3余0、除以5余0、除以7余2;

那么令 [公式] ,就很容易验证这时的 [公式] 就满足除以3余2、除以5余3、除以7余2。

分别称找到整数 [公式] 的问题为问题1-1、问题1-2、问题1-3。可以看出这三个问题本质上是类似的。

 

 

普通的中国剩余定理要求所有的互素,那么如果不互素呢,怎么求解同余方程组?

  这种情况就采用两两合并的思想,假设要合并如下两个方程:

  那么得到:

  我们需要求出一个最小的xx使它满足:

  那么x1x1和x2x2就要尽可能的小,于是我们用扩展欧几里得算法求出x1x1的最小正整数解,将它代回a1+m1x1,得到x的一个特解x,当然也是最小正整数解。

  所以xx的通解一定是x加上lcm(m1,m2)k,这样才能保证xm1m2的余数是a1a2。由此,我们把这个xx′当做新的方程的余数,把lcm(m1,m2)当做新的方程的模数。(这一段是关键

  合并完成:

代码:

#include<bits/stdc++.h>
using namespace std; int const MAXN=10010; int x,y; int k;//k组同余方程
int a[MAXN];//每个同余方程的余数
int b[MAXN];//每个同余方程的模数
int ans; int lcm=1; void exgcd(int a,int b) { if(b==0){x=1;y=0;} else{ exgcd(b,a%b); int tmp=x; x=y; y=tmp-a/b*y; } return; } int main() { cin>>k; for(int i=1;i<=k;++i) cin>>b[i]>>a[i]; for(int i=1;i<=k;++i) lcm*=b[i]; for(int i=1;i<=k;++i) { exgcd(lcm/b[i],b[i]); x=(x%b[i]+b[i])%b[i]; ans=(ans+(lcm/b[i])*x*a[i])%lcm; } cout<<ans; }

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM