引言
大衍求一術是秦九韶發明的一種求特殊一次同余式的方法,以下摘自百度百科
秦九韶,字道古,生活於南宋時期,自幼喜好數學,經過長期積累和苦心鑽研,於公元1247年寫成《數書九章》。這部中世紀的數學傑作,在許多方面都有創造,其中求解一次同余組的“大衍求一術”和求高次方程數值解的“正負開方術”,更是具有世界意義的成就。
進入正題
對於形如ax ≡ 1 (mod n),(a,n) = 1的同余式,秦九韶的大衍求一術給出了一種優秀的解法。
注意a,n必須互素
第一步我們令k0 = 0,k1 = 1, r0 = n, r1 = a,(k叫乘率,也是最后答案)
第二步我們讓 r0 和 r1 作帶余除法,即 r0 = q2r1 + r2,
第三步我們用 r1 和 r2 作帶余除法,即r1 = q3r2 + r3
...
直到出現rn = 1, 這時我們帶回同余方程
定義kn = kn-2 - qnkn-1,依次回代求得kn即是同余方程的解
舉個栗子
37x ≡ 1 (mod 73)
(37,73)=1,所以滿足使用大衍求一術的條件
首先我們令k0 = 0,k1 = 1,r0= 73,r1=37
r0/r1: 73=37*1+36 =>q2=1,r2=36
r1/r2: 37=36*1+1 =>q3=1,r3=1
此時r3=1,停止除法,代回求解
k2=k0-q2k1,
k3=k1-q3k2
=>k3=2
因此37 x≡ 1 (mod 73)的解為
x ≡ 2 (mod 73)
代碼實現
1 int dyqy(int a, int p) 2 { 3 if (__gcd(a, p) != 1) 4 return -1; //不能用大衍求一術 5 vector<int> k, r, q; 6 k.emplace_back(0), k.emplace_back(1); //k0=0,k1=1 7 r.emplace_back(p), r.emplace_back(a); //r0=p,r1=a 8 q.emplace_back(-1), q.emplace_back(-1); 9 int i = 0; 10 while (1) 11 { 12 int ra = r[i], rb = r[i + 1]; 13 int qtmp = ra / rb; 14 int rtmp = ra % rb; 15 q.emplace_back(qtmp); 16 r.emplace_back(rtmp); 17 ++i; 18 if (rtmp == 1) 19 break; 20 } 21 int sz = r.size(); 22 for (int i = 2; i < sz; i++) 23 { 24 int ktmp = k[i - 2] - k[i - 1] * q[i]; 25 k.emplace_back(ktmp); 26 } 27 return k.back(); 28 }
