https://www.zybuluo.com/ysner/note/1221126
單個同余方程
求解形如\(Ax\equiv B(mod\ M)\)的最小正整數解。
il void exgcd(re ll A,re ll B,re ll &D,re ll &x,re ll &y)
{
if(!B) x=1,y=0,D=A;
else exgcd(B,A%B,D,y,x,c),y-=(A/B)*x;
}
il void solve2()
{
re ll A=atk[1],B=a[1],M=p[1],D,x,y,ysn,zsy;
exgcd(A,M,D,x,y);//D=gcd(A,M)
if(B%D) {puts("-1");return;}
x=x*(B/D)%(M/D);
printf("%lld\n",x);
}
解釋一下:
\(Ax\equiv B(mod\ M)\)
\(Ax=My+B\)
\(Ax+My=B\)(正負號不重要)
於是就是解\(Ax+My=B\)這個不定方程。
根據斐蜀定理:\(ax+by=c=k*gcd(a,b)(k\in N^{*})\)
所以必須\(gcd(A,M)|B\),否則無解。
設\(a>b\)。
當\(b=0,gcd(a,b)=a\),所以此時\(x=1,y=0\)
當\(a>b>0\)時,設\(ax_1+by_1=gcd(a,b),bx_2+(a\ mod\ b)y_2=gcd(b,a\ mod\ b)\)
根據歐幾里德原理,則
\(ax_1+by_1=bx_2+(a\ mod\ b)y_2\)
即\(ax_1+by_1=bx_2+(a-(a/b)*b)y_2=ay_2+bx_2-(a/b)*by_2\)
對應得\(x_1=y_2,y_1=x_2-(a/b)*y_2\)
於是我們就可以一邊求\(gcd\)一邊解這個方程。
當然,注意到跑了\(exgcd\)后解出來的是\(ax+by=gcd(a,b)\)
解同時乘上\(c/gcd(a,b)\)即可。
注意到\(x,y\)的解不止一個,\(x+=b/gcd(a,b),y-=a/gcd(a,b)\)后總是合法。(因為加減的都是\(ab/gcd(a,b)=lcm(a,b)\))。
為了求最小正整數值,我們模這個值即可。
如果要把最后一步套路化,就是\(D=gcd(A,B),x=z*(B/D)\%(M/D)\)
模數互質的同余方程組
用中國剩余定理(孫子定理)解決。
講這玩意兒需要栗子。
在《孫子算經》中有這樣一個問題:“今有物不知其數,三三數之剩二(除以\(3\)余\(2\)),五五數之剩三(除以\(5\)余\(3\)),七七數之剩二(除以\(7\)余\(2\)),問物幾何?”
首先,我們假設\(n_1\)是滿足除以\(3\)余\(2\)的一個數。同樣,我們假設\(n_2\)是滿足除以\(5\)余\(3\)的一個數,\(n_3\)是滿足除以\(7\)余\(2\)的一個數。
現在把\(n_1+n_2+n_3\)作為該問題最終解。
則依“兩數相加則模數相加”:
- \(n_1\)除以\(3\)余\(2\),且是\(5\)和\(7\)的公倍數。
- \(n_2\)除以\(5\)余\(3\),且是\(3\)和\(7\)的公倍數。
- \(n_3\)除以\(7\)余\(2\),且是\(3\)和\(5\)的公倍數。
所以,孫子問題解法的本質是對每一個方程,從其它所有模數公倍數中找出符合該方程的解,最終解就是這些解相加。
在求\(n_1\),\(n_2\),\(n_3\)時又用了一個小技巧,以\(n_1\)為例,並非從\(5\)和\(7\)的公倍數中直接找一個除以\(3\)余\(2\)的數,而是先找一個除以\(3\)余\(1\)的數,再乘以\(2\)。也就是找解時先求出公倍數模數下的逆元,再用逆元去乘余數。
找逆元和解單個同余方程一樣。
模數不互質的同余方程
用拓展中國剩余定理解決。
還是栗子。
有一同余方程組:(注意到\(x\)沒有系數)
\(x\equiv b_1(mod\ m_1)\)
\(x\equiv b_2(mod\ m_2)\)
則\(x=k_1m_1+b_1=k_2m_2+b_2\)
發現右邊兩個表達式相等可以看做一個方程\(m_1k_1+m_2k_2=b_2-b_1\)
顯然可以拓歐求解\(k_1,k_2\)。
又由斐蜀定理可知,\(m_1x+m_2y=gcd(m_1,m_2)\)
所以\(k_1=\frac{b_2-b_1}{gcd(m_1,m_2)}\)
將\(k_1\)代入\(x=b_1+k_1m_1\)即可得出特解\(x'\)
如果解出特解\(x'\),則\(x=x'+k*lcm(m_1,m_2)\)。
則\(x\equiv x'(mod\ lcm(m_1,m_2))\)
這個方程的解就是整個方程組的解。
