中國剩余定理(孫子定理)詳解 (轉)
問題:今有物不知其數,三三數之剩二,五五數之剩三,七七數之剩二。問物幾何?
說明白一點就是說,存在一個數x,除以3余2,除以5余三,除以7余二,然後求這個數。上面給出了解法。再明白這個解法的原理之前,需要先知道一下兩個定理。
定理1:幾個數相加,如果存在一個加數,不能被數a整除,那麽它們的和,就不能被整數a整除。
定理2:兩數不能整除,若除數擴大(或縮小)了幾倍,而被除數不變,則其商和余數也同時擴大(或縮小)相同的倍數(余數必小於除數)。
這兩個定理淺顯易懂,自己找個例子就能理解,就不再贅述了。
現給出求解該問題的具體步驟:
1、求出最小公倍數
lcm=3*5*7=105
2、求各個數所對應的基礎數
(1)105÷3=35
35÷3=11......2 //基礎數35
(2)105÷5=21
21÷5=4......1
定理2把1擴大3倍得到3,那麽被除數也擴大3倍,得到21*3=63//基礎數63
3、105÷7=15
15÷7=2......1
定理2把1擴大2倍得到2,那麽被除數也擴大2倍,得到15*2=30//基礎數30
把得到的基礎數加和(註意:基礎數不一定就是正數)
35+63+30=128
4、減去最小公倍數lcm(在比最小公倍數大的情況下)
x=128-105=23
那麽滿足題意得最小的數就是23了。一共有四個步驟。下面詳細解釋每一步的原因。
(1)最小公倍數就不用解釋了,跳過(記住,這裏討論的都是兩兩互質的情況)
(2)觀察求每個數對應的基礎數時候的步驟,比如第一個。105÷3=35。顯然這個35是除了當前這個數不能整除以外都能夠被其他數整除,就是其他數的最小公倍數。相當於找到了最小的開始值,用它去除以3發現正好余2。那麽這個基礎數就是35。記住35的特征,可以整除其他數但是不能被3整除,並且余數是2。體現的還不夠明顯,再看下5對應的基礎數。21是其他數的最小公倍數,但是不能被5整除,用21除以5得到的余數是1,而要求的數除以5應該是余1的。所以余數被擴大,就得到了相應的基礎數63。記住這個數的特征,可以被其他數整除但是被5除應該余三。同理,我們得到了第三個基礎數23,那麽他的特征就是:可以被其他數整除,但是不能被7整除,並且余數為2。
(3)第三步基礎數加和,為什麽要這樣做呢?利用就是上面提到的定理1。
35+63+30=128。對於3來說,可以把63+30的和看作一個整體,應該他們都可以被3整除。看著上面寫出的三個數的特征,運用定理1來說,就是在35的基礎上加上一個可以被3整除的倍數,那麽得到的結果依然還是滿足原先的性質的,就是128除以同樣還是余2的。同理,對於5還說,這個數被除之後會剩余3;對於7來說,被除之後剩余2。所以說,我們當前得到的這個數是滿足題目要求的一個數。但是這個數是不是最小的,那就不一定了。
(4)應該不能確定是不是最小的數,這個時候就要用到他們的最小公倍數了。最小公倍數顧名思義,一定是一個同時被幾個數整除的最小的一個數,所以減去它剩余下來的余數還是符合題意要求的。當然也同樣可以運用定理1來解釋,只不過是加法變成了減法,道理還是一樣的。當然具體要不要剪還是要看和lcm的大小關系的。
稍微的總結一下:就是已知m1,m2,m3是兩兩互質的正整數,求最小的正整數x,使它被m1,m2,m3除所得的余數分別是c1,c2,c3。孫子定理的思想便是線分別求出被其中數mi整除余1而被兩外兩個數整除的數Mi(i=1,2,3),則所求數之一的便是c1M1+c2M2+c3M3。由此我們可以得到n個兩兩互質數的情況。證明上面已經一步一步給出。
那麽,到此為止基本的中國剩余定理的內容我們以及了解了,包括解答方法。那麽如何編碼呢?按照上面這個思路去編碼,其實並不難。一共分為四大步。但是,大多數人的困惑在於如何求取基礎數。這裏呢,提供兩種方法:
(1)第一種就是一直遞增,直到找到。例如:3的基礎數,35是其他數的最小公倍數。那麽就從35開始,一直自增,知道余數為2,便停止(利用while循環)。
(2)第二種方法呢就是輾轉相除法上得來的。這裏的例子體現的不夠明顯,應當看看去求取乘法逆元的過程,下面講的內容和乘法逆元有很大的關系,所以還是看看的好。簡單舉個例子:
假設現在三個數分別是14,3,5,它們兩兩互質,且要求的數除以5余3。求5對應的基礎數。有:
42÷5=8......2
5÷2=2......1
所以1=5-2*2=5-2*(42-8*5)=-2*42+17*5
那麽-2*42=-84 17*5=85 -84+85=1
把1擴大3倍變成3,則有-84*3=-252也就是5對應的基礎數。
第一點: 基礎數可以是負數,這個之前點到過。//並且下面的解法就是有這樣的。
第二點: 當得到余數為1的時候後面的算式相當於是一個回溯的過程,最後解到-2*42。 但是還只不過是余數是1的情況對應的數,再運用定理2我們就得到了-252這個基礎數。實際上要是看過乘法逆元,這裏實際就是乘法逆元的求解過程,而-2也就是42關於15取模的乘法逆元。
模板:
1 /*long long gcd(LL a,LL b) 2 { 3 return b==0?a:gcd(b,a%b); 4 }*/ 5 #include<cstdio> 6 #define ll long long 7 //擴展歐幾裏得算法 8 void gcd(ll a,ll b,ll &d,ll &x,ll &y) 9 { 10 if(b==0){ 11 d=a; 12 x=1,y=0; 13 } 14 else{//else不能省略 15 gcd(b,a%b,d,y,x); 16 y-=(a/b)*x; 17 } 18 } 19 //中國剩余定理 20 ll China(int n,ll *m,ll *a) 21 { 22 ll M=1,d,y,x=0; 23 for(int i=0;i<n;i++) M*=m[i]; 24 for(int i=0;i<n;i++){ 25 ll w=M/m[i]; 26 gcd(m[i],w,d,d,y); 27 x=(x+y*w*a[i])%M; 28 } 29 return (x+M)%M; 30 } 31 ll m[15],a[15]; 32 int main() 33 { 34 int n; 35 scanf("%d",&n); 36 for(int i=0;i<n;i++) 37 scanf("%lld%lld",&m[i],&a[i]); 38 printf("%lld",China(n,m,a)); 39 }
中國剩余定理(孫子定理)詳解 (轉)