中国剩余定理

中国剩余定理

中国剩余定理可以描述为:

若某数x分别被d1、、dn除得的余数为r1r2rn,则可表示为下式:
x=R1r1+R2r2+…+Rnrn+RD
其中R1d2d3dn的公倍数,而且被d1除,余数为1;(称为R1相对于d1的数论倒数)
R1

R2

 

Rnd1d2dn-1的公倍数,而且被dn除,余数为1
D
d1d2、的最小公倍数;
R
是任意整数(代表倍数),可根据实际需要决定;
d1、、、必须互质,以保证每个Ri(i=1,2n)都能求得.

(注:因为R1d1求余为1,所以R1r1d1求余为r1,这就是为什么是R1d1求余为1的目的,其次,R2r2,R3r3…Rnrnd1求余都是0

 

如要讨论中国利余定理,同余(congruence的概念可算是必须。

给定一个正整数n,我们说两个数ab是对模n同余,如果a-bn的倍数。用符号ab(mod n)来代表。一般来说,ab(mod n)等同于ab+kn,而abkn都是整数,所以,131(mod 6)191(mod 6) 

但同余并不只是一个代号,而是有很方便和有趣的特性。(一)整数加法跟普通加法相似,a+c(b+c)(mod n);(二)整数乘法跟普通乘法相似,acbc(mod n),而abcn都是整数。但如果acbc(mod n),则不一定ab(mod n)
 

「鬼谷算」为例,假设x是那个未知数,而除357后的余数分别为r1r2r3。因此有
 

x
r1(mod
 3) 
 
x
r2(mod
 5) 
 
x
r3(mod
 7) 
 
而另一方面


70
(5x7)x21(mod 3)700(mod 5)700(mod 7) 
 
21
(3x7)x11(mod 5)210(mod 3)210(mod
 7) 
 
15
(3x5)x11(mod 7)150(mod 3)150(mod
 5) 
 
由同余的特性,我们有
 

70r1
r1(mod 3)70r10(mod 5)70r10(mod
 7) 
 
21r2
0(mod 3) 21r2r2(mod 5)21r20(mod
 7) 
 
15r3
0(mod 3) 15r30(mod 5)15r3r3(mod
 7) 
 

因此亦有
 

70r1+21r2+15r3
r1(mod
 3) 
 
70r1+21r2+15r3
r2(mod
 5) 
 
70r1+21r2+15r3
r3(mod 7) 

所以

x70r1+21r2+15r3+3m

x70r1+21r2+15r3+5n
x
70r1+21r2+15r3+7p

 
最后得到这个精彩的结果,x(70r1+21r2+15r3)(mod 105),而105正便是357的最小公偣数。所以其实在很多数字可以满足这几个余数条件的,要找到最小值才要减105

 

对于中国剩余定理有个简单理解并记忆的方法:

中国剩余定理的思想在于先找到一个满足条件的数,不管是不是最小的,如果不是最小的就不断减公倍数,中国剩余定理的巧妙在于把满足条件的数分成三个部分相加,例如:
假设满足条件的数为:M=3*5*a+5*7*b+3*7*c
先让它满足条件1:除以31,我们看M的第一部分和第三部分能被3整除,只要第二部分除以31就行了,选择b=2就满足

再满足条件2:除以52,考虑第三部分就行了,选择c=2就满足
最后满足条件3:除以73,考虑第一部分就行了,选择a=3
这样M=3*5*3+5*7*2+3*7*2=157,比公倍数大,减去公倍数,157-105=52是满足条件最小数

 

以我个人理解写成下面这个形式(以3个数为例)

Xa,b,c处分别余r1,r2,r3。表示为:

X%a = r1                     x%b = r2                     x%c = r3

bc*k1 % a = 1     ac*k3 % b = 1     ab*k3 % c = 1

所以

x = bc * k1 * r1 + ac * k2 * r2 + ab * k3 * r3

 

 

 

下面以一个例子来把中国剩余定理用于实践

POJ1006http://acm.pku.edu.cn/JudgeOnline/problem?id=1006&lang=zh-CN&change=true

解答报告:

#include int main() { int R1 = 5544, R2 = 14421, R3 = 1288, R = 21252; int ph, em, in, day; int res,i; for(i=1; 1; i++){ scanf("%d%d%d%d", &ph, &em, &in, &day); if(ph==-1)break; res = (R1 * ph + R2 * em + R3 * in – day) % R; res = (res + R – 1) % R + 1;//若上面的res是负数则使res变成正数 printf("Case %d: the next triple peak occurs in %d days./n", i, res); } return 0; } /**************************************************** //find the value of R1, R2 and R3 according to 中国剩余定理 int main() { int i; int R1, R2, R3; for(i=1, R1=28*33; 1; i++) if(R1*i%23==1)break; R1 *= i; for(i=1, R2=23*33; 1; i++) if(R2*i%28==1) break; R2 *= i; for(i=1, R3=23*28; 1; i++) if(R3*i%33==1) break; R3 *= i; printf("R1 = %d /nR2 = %d/nR3 = %d/n",R1,R2,R3); return 0; } *****************************************************/

 

 

 

C++奋斗乐园①群(已满):19333724

C++奋斗乐园②群:23840480

我们的论坛(刚建立。。。) www.cppleyuan.com  (C++奋斗乐园)

你可能感兴趣的:(POJ解答报告,c)