線性同餘方程組的形式
實際上一元一次線性同餘方程組,形式如下:
包含有具體數字的線性同餘方程組問題最早見於《孫子算經》(成書於約南北朝時期,因此與《孫子兵法》的孫子應該不是同一個孫子),該書也給出了該具體問題的解法。因此求解線性同餘方程組有關的定理又稱作孫子定理。但實際上《孫子算經》並未給出證明及一般性解法。最早的系統性論述應該是南宋時期秦九韶在《算術九章》中提出的“大衍求一術”。因此最後有關該問題的理論被稱作中國剩餘定理。
中國剩餘定理
如果 兩兩互質,則方程有唯一解,在模 的意義下。解法如下:
令 ,且
對每一個 求出在模 意義下的逆元,記作
即滿足
則原方程組的解爲
線性同餘方程組的一般解法
使用中國剩餘定理理論上可以很方便的解出模數兩兩互質的方程組。對於不互質的情況可以使用下面的一般解法。
單獨的線性同餘方程求解
考慮單獨的一個線性同餘方程,已知 ,求 滿足如下方程:
原方程等價於:
根據裴蜀定理,上述方程有解的充要條件是 是 的整數倍。利用擴展的擴展的歐幾里德算法可以很容易求得 使得:
於是很容易得到 的一個特解爲:
顯然 有無窮多解,如果考慮在模 的意義下, 也有 個不同的解,且成等差數列,公差爲 。因此很容易求得最小正整數解爲:
考慮方程
根據擴展的歐幾里德算法有:
得到 的一個解爲11,所以 的一個解爲22,對4取模即可得到最小正整數解2,且在模12的意義下有3個解,分別是2、6、10。
兩個線性同餘方程合併
考慮2個線性同餘方程構成的方程組:
分別等價於
因此有
兩邊對 取餘數即可得到一個單獨的關於 線性同餘方程
根據之前的結論,很容易判斷是否有解並可以解出 。如果可解,可以得到一個方程:
該方程與原方程組等價。其中 爲最小公倍數。
如此反覆,就可以將線性同餘方程組合併爲一個方程,並且利用擴展的歐幾里德算法求解。在每一步中,均需判斷是否有解。
typedef long long int llt;
//to convert two congruence equations to equivalent one
//x = r1 (mod m1)
//x = r2 (mod m2)
//the out put is: x = r3 (mod m3)
//return true if there is a solution, otherwise false
bool mergeCrt(llt r1,llt m1,llt r2,llt m2,llt&r3,llt&m3){
llt x,y;
llt g = exEuclid(m1,m2,x,y);
llt r = (r2 - r1) % m2;
if ( r < 0 ) r += m2;
if ( r % g ) return false;//no solution
x = r / g * x % ( m2 / g );//the least positive solution
m3 = m1 / g * m2; //lcm
r3 = ( ( x * m1 ) % m3 + r1 ) % m3;
return true;
}
//Chinese remainder theorem to solve linear congruence equations
//n is the count of equations
//remainder is the array of remainders, index from 0
//mod is the array of modules, index from 0
//return the least positive solution or -1 if there is no solution
llt Crt(int n,llt const remainder[],llt const mod[]){
llt r1 = remainder[0],m1 = mod[0];
for(int i=1;i<n;++i){
if ( !mergeCrt(r1,m1,remainder[i],mod[i],r1,m1) ){
return -1;
}
}
r1 %= m1;
if ( r1 < 0 ) r1 += m1;
return r1;
}
完整的程序可以見POJ2891