中國剩餘定理講解
中國剩餘定理講解
1.運用領域
擴充套件中國剩餘定理是解決向下面列出的一元線性同餘方程組的一種數論知識,可以求出下面方程組中最下的正整數$x$。但是擴充套件中國剩餘定理和中國剩餘定理有什麼區別呢?中國剩餘定理對於$mod$是有限制的,他對於$mod$要求為兩兩互質,然而擴充套件中國剩餘定理對於$mod$沒有要求。
$\begin{cases} x\equiv x_1 (mod_1)\\ x\equiv x_2 (mod_2)\\ \ \ \ \ \ \ \vdots \ \ \ \ \ \ \ \ \ \ \vdots & \\x\equiv x_3 (mod_3)\end{cases} $
2.前置知識
學習擴充套件中國剩餘定理之前需要學習擴充套件$gcd$,以及一些簡單的數學小知識。
3.講解
注:博主部分證明的學習資源來自JZYshuraK的部落格。
首先我們看上方列出的方程組,我們選擇最上方的兩個方程,看能不能合成。
我們將上面的通與方程進行變形可以得到下面的一個方程組。
$\begin{cases} x=x_1+k_1\times mod_1 \\ x=x_2 +k_2\times mod_2 \end{cases}$
我們可以根據上面的方程組得到一個式子$x_1+k_1\times mod_1=x_2+k_2\times mod_2$,我們將這個式子進行移項可以得到$k_1\times mod_1+(-k_2)\times mod_2=x_2-x_1$,這個式子很像$ax+by=c$的形式,所以很容易想到用擴充套件$gcd$,我們用擴充套件$gcd$可以求出來$k_1$的通項,但是前提是$gcd(mod_1,mod_2)| (x_2-x_1)$,如果上面的前提不滿足,則這個同餘方程組無法滿足。
我們設$K_1,K_2$為$K_1\times mod_1+(-K_2)\times mod_2=gcd(mod_1,mod_2)$的兩個特解。我們將式子兩邊都乘以$\frac{(x_2-x_1)}{gcd(mod_1,mod_2)}$,就能知道上述式子$k_1=K_1\times\frac{(x_2-x_1)}{gcd(mod_1,mod_2)}$,$k_2=K_2\times\frac{(x_2-x_1)}{gcd(mod_1,mod_2)}$。我們將$k_1,k_2$迴帶到原來的式子,能得到一個方程組(下方)。
$\begin{cases} x=x_1+K_1\times\frac{(x_2-x_1)}{gcd(mod_1,mod_2)}\times mod_1 \\ x=x_2 +K_2\times\frac{(x_2-x_1)}{gcd(mod_1,mod_2)}\times mod_2 \end{cases}$
顯然滿足這個方程組的$K_1,K_2$不只一組,並且每一組$K_1,K_2$都對應一個$x$,所以我們能知道每兩個解$\Delta$就是$\frac{(x_2-x_1)}{gcd(mod_1,mod_2)}\times mod_1$和$\frac{(x_2-x_1)}{gcd(mod_1,mod_2)}\times mod_2$的倍數,所以$\Delta$一定是$\frac{mod_1\times mod_2}{gcd(mod_1,mod_2)}$的倍數,即$\Delta$是$lcm(mod_1,mod_2)$的倍數。我們就能知道$x=k_1\times mod_1+x_1+t\times lcm(mod_1,mod_2)$。這樣我們就將上面兩個同餘方程合成為$x \equiv k_1\times mod_1+x_1 (lcm(mod_1,mod_2))$。
我們可以用$O(log)$,運用$Exgcd$合併兩個同餘方程,一共做$n$次,就能將所有的同餘方程合併在一起了。最後我們得到的同餘方程就是所有的$x$的通式。
程式碼(模板),下面以有$n$個同餘方程為例。
#define ll long long ll Exgcd(ll a,ll b,ll &x,ll &y) { if(!b) {x=1,y=0;return a;} ll gcd=Exgcd(b,a%b,x,y),tmp=x; x=y,y=tmp-a/b*y; return gcd; } ll Ex_crt() { ll lcm=mod[1],last_x=x[1]; for(int i=2;i<=n;i++) { ll lcm_a=((x[i]-last_x)%mod[i]+mod[i])%mod[i],x,y,k=lcm; ll gcd=Exgcd(lcm,mod[i],x,y); x=(x*lcm_a/gcd%(mod[i]/gcd)+(mod[i]/gcd))%(mod[i]/gcd); lcm=lcm*mod[i]/gcd,last_x=(last_x+k*x)%lcm; } return (last_x%lcm+lcm)%lcm; }
如果有不懂的地方或者有所寫有不對的地方,可以發評論,我會進行解答或改正。