中國剩余定理(CRT) and 擴展中國剩余定理(EXCRT)


今有物不知其數,三三數之余二;五五數之余三;七七數之余二。問物幾何?

語文水平不高,大概翻譯一下:

今天Rothen釣了幾個妹子,3個3個的數會余下2個,5個5個的數會余下3個,七個七個的數會剩下2個

好吧,這樣好像更難理解了,懶得翻譯了,反正大家都看得懂,大佬們就先做會吧,反正對於您這種神犇那肯定是秒切啊!。

 

中國剩余定理???好高級的東西啊,嚇得我趕緊來個BFS( Baidu First Search)

發現中國剩余定理又叫孫子定理,原因是孫子發明的(這名字絕了)

然后對於上面的題目的解法為:

(注意,中國剩余定理的解法只能用於幾個模數兩兩互質的情況)

1.首先找出5和7的 mod 3等於1的公倍數(70),然后找出3和7的mod 5 等於1的公倍數(21),還有就是3 和 5的mod 7等於1的公倍數(15)

2.答案就是上面求出來的三個數的乘積分別乘以"對應的余數" mod 所有模數的乘積 例如 (70*2+21*3+15*2)mod (7*3*5)得到23

 

納尼!這么神奇的嗎?

真的就是這么神奇哦~

本蒟蒻查閱對於這個定理的證明為:

把上面的問題轉化為多個個子問題:

假設存在一個數x1 % 3 =2("%"就是取余數),那么x1就能表示為3k+2的形式(k >= 0)

假設存在一個數x2 % 5 =3("%"就是取余數),那么x1就能表示為5k+3的形式(k >= 0)

假設存在一個數x3 % 7 =2("%"就是取余數),那么x1就能表示為7k+2的形式(k >= 0)

那么考慮如果存在一個

x1 + x2 + x3使得它們滿足上面的所有條件呢?

首先有個特別基礎的公式:A % B = C, 那么(A + B*K) % B =C

這個應該很好理解,你可以這么想:跟上面的類似,A可以表示為 若干倍的B加上C,

而A+B*k就可以表示為:若干倍的B + C +K倍的B ,自然的對於(A+B*k)%B也是等於C了啊!

回到剛才的問題,怎么樣才能使得x1+x2+x3滿足條件呢?

若要使得(x1+x2+x3)%3仍然余下2,那么x2,x3就一定要是三的倍數

若要使得(x1+x2+x3)%5仍然余下3,那么x1,x3就一定要是五的倍數

若要使得(x1+x2+x3)%7仍然余下2,那么x1,x2就一定要是七的倍數

 

 所以問題就轉化為了求出x1,x2,x3

哦吼,從上面我們看出了x1,x2,x3的幾個性質:

1.x1是5和7的公倍數,而且x1 % 3  = 2

2.x2是3和7的公倍數,而且x2 % 5 =  3

3.x3是3和5的公倍數,而且x3 % 7 =  2

同時又引入一個數學公式:

如果a%b=c,那么(a*k)%b=(a%b+a%b+a%b+...+a%b(k個a%b)   ) mod   b=c×k mod b

然后問題就可以用開篇的方法解決了呀!而且找出來的是最小滿足條件的數。

 

妙啊!

 

例題:

P1495 【模板】中國剩余定理(CRT)/曹沖養豬

 

板子,不多贅述。

 

放上我這丑的一批的代碼:

#include <bits/stdc++.h>
#define int long long
using namespace std;
int n,a[15],b[15],c[15],q=1,sum=0;
signed main(){
    cin>>n;
    for (int i = 1 ; i <= n ; i ++)
    cin>>a[i]>>b[i],q*=a[i];
    for (int i = 1 ; i <= n ; i ++){
        if(a[i] == 1)continue;
        q/=a[i];
        int j=1;
        while(q*j % a[i] != 1)j++;//找其他幾個數的公倍數%a[i]等於一的數
        c[i]=q*j;
        q*=a[i];
    }
    for (int i = 1 ; i <= n ; i ++)
        sum+=c[i]*b[i],sum%=q;
    cout<<sum%q;
    return 0;
}

注意:中國剩余定理只能用於每一個a[i]都兩兩互質的情況,但是如果它們不是兩兩互質的,我們就要用   “擴展中國剩余定理

 

擴展中國剩余定理是中國剩余定理的"進階版"

 

那么擴展中國剩余定理的使用情況是怎么樣的呢?

因為上面也提到了:“注意,中國剩余定理的只能用於幾個模數兩兩互質的情況”,所以擴展中國剩余定理就是可以適用於模數不兩兩互質的情況。

那這怎么搞啊?

聰明的數學家們又找到了一種辦法:

將原來的余數方程列出來

假設現在我們已經求出來了前k-1個方程的解是x,現在加入了第k個方程

設前k-1個方程的模數的乘積是M,我們現在就是要求一個數字P使得

(x + P*M) % 第k個模數  = 第k個余數

這個P是可以通過擴展歐幾里得算法算出來的,所以就可以很快求出P來。

 

這個問題又解決了,妙啊!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM