1. 程式人生 > 實用技巧 >14.表達整數的奇怪方式 中國剩餘定理 --------待複習標誌--------

14.表達整數的奇怪方式 中國剩餘定理 --------待複習標誌--------

中國剩餘定理,又叫孫子定理

中國剩餘定理是用來求解同餘方程組的

給定一堆兩兩互質的數,m1, m2, ..., mk

用M表示所有mi的乘積

再定義Mi =除了mi後,所有m的乘積。所以Mi和mi互質

這一步是用擴充套件歐幾里德演算法

求逆等價於特殊的方程,右邊不是b了,是1

由於m不一定是質數,所以用擴充套件歐幾里德演算法來求

先拿兩個式子為例,分析一下

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 ll exgcd(ll a, ll b, ll &x, ll &y) { //
擴充套件歐幾里德演算法模板 5 if (!b) { 6 x = 1; 7 y = 0; 8 return a; 9 } 10 ll d = exgcd(b, a % b, y, x); 11 y -= a / b * x; 12 return d; 13 } 14 int main() { 15 int n; 16 cin >> n; 17 bool has_answer = true; 18 ll a1, m1; //假設第一個方程是x mod a1 = m1
19 //要將兩個式子合併成x = k * a1 + m1的形式 20 cin >> a1 >> m1; 21 for (int i = 0; i < n - 1; i++) { //然後把剩餘方程合併入現有方程中 22 ll a2, m2; //假設新的方程是x mod a2 = m2 23 cin >> a2 >> m2; 24 //然後開始合併 25 //根據這個式子k1 * a1 - k2 * a2 = m2 - m1 (*) 26 ll k1, k2; //
要求出來上式的係數 27 ll d = exgcd(a1, a2, k1, k2); //d = a1和a2的最大公約數 28 if ((m2 - m1) % d) { //若*式無解 29 has_answer = false; 30 break; 31 } 32 //能走到這說明有解 33 //上面用拓展歐幾里德演算法求出來的實際是 34 //k1 * a1 - k2 * a2 = d的係數 35 k1 *= (m2 - m1) / d; //等式兩邊同時乘以 36 ll t = a2 / d; //根據k1 + k * (a2 / d) 37 //只要求出一個k1,就能求出其通解 38 //k1 + k * (a2 / d) 39 k1 = (k1 % t + t) % t; //然後把k1變成最小的正整數解 40 //要將兩個式子合併成x = k * a1 + m1的形式 41 m1 = a1 * k1 + m1; 42 a1 = abs(a1 / d * a2); //新式子的係數a1 43 44 } 45 if (has_answer) { 46 cout << (m1 % a1 + a1) % a1 << endl; 47 } else { 48 cout << -1 << endl; 49 } 50 return 0; 51 }