大衍求一術的計算方法


引言

大衍求一術是秦九韶發明的一種求特殊一次同余式的方法,以下摘自百度百科

秦九韶,字道古,生活於南宋時期,自幼喜好數學,經過長期積累和苦心鑽研,於公元1247年寫成《數書九章》。這部中世紀的數學傑作,在許多方面都有創造,其中求解一次同余組的“大衍求一術”和求高次方程數值解的“正負開方術”,更是具有世界意義的成就。


 

進入正題

對於形如ax ≡ 1 (mod n),(a,n) = 1的同余式,秦九韶的大衍求一術給出了一種優秀的解法。

注意a,n必須互素

第一步我們令k= 0,k= 1, r= n, r= a,(k叫乘率,也是最后答案)

第二步我們讓 r0  r1 作帶余除法,即 r= q2r+ r2,

第三步我們用 r1 和 r2 作帶余除法,即r1 = q3r2 + r3

...

直到出現r= 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 }
大衍求一術

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM