日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

如何利用扩展欧几里得算法求解不定方程_客户端不用的算法系列:从头条笔试题认识扩展欧几里得算法...

發布時間:2025/3/19 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何利用扩展欧几里得算法求解不定方程_客户端不用的算法系列:从头条笔试题认识扩展欧几里得算法... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

難度較高,閱讀時間大概 28 分鐘

這是數論的第二篇,在《素數篩法》中,我們重溫了素數這個數學定義,并且給出了區別于教科書上更高效的 Eratosthenes 篩法歐拉線性篩。這篇文會從 GCD 問題出發,一起來探究一下擴展歐幾里得算法。

看了標題,也許你有疑問,什么是歐幾里得算法?歐幾里得算法是為了解決 GCD 問題,這里的 GCD 是指 Greatest Common Divisor 即?最大公約數,而不是 iOS 中的 Grand Central Dispatch ? 。所以這篇分享是關于算法的。

歐幾里得算法(GCD)

求 GCD 在數論中公認的最常用算法即為歐幾里得算法,也就是我們在高中時學到的輾轉相除法

歐幾里得算法的基本原理用一句話就可以說清楚:兩個整數的最大公約數等于其中較小的數和兩數的差的最大公約數,即 gcd(a, b) = gcd(b, a mod b)

為什么可以這么求呢,這里可以簡單證明一下:

假設 a, b (a > b) 兩個數的一個公約數是 t ,則有

因為 a > b ,設 a = k × b + r ,即 r = a mod b ,將 a、b 代入展開可得:

由于 (n - k × m) × t 一定是整數,所以 a、b 的公約數 t 也是 r 的約數。所以如果我們遞歸的求解 a mod b 也就是 a % b ,就可以得到 a、b 的最大公約數 GCD 了。什么時候遞歸結束呢?當 a % b == 0 的時候,因為在這個過程中,如果 a mod b 無法求得正整數 r 時,則無法繼續按照上述規律繼續拆分。

# pythondef gcd(a, b): return a if b == 0 else gcd(b, a % b)// Cint gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b);}

這里另外提一句,a、b 兩數的最大公倍數 LCM(a, b) = a * b / GCD(a, b) 。這里就不證明了,有興趣的自己谷歌。

一道頭條的筆試題

上個月在脈脈上看到一道頭條校招的筆試題,看評論說是“地獄難度”的,我們通過這道題來延伸說一下。先來看下這題的題面:


有一臺用電容組成的計算器,其中每個電容組件都有一個最大容量值(正整數)。對于單個電容,有如下操作指令:

指令1:放電操作-把該電容當前電量值清零;

指令2:充電操作-把該電容當前電量補充到最大容量值;

指令3:轉移操作-從電容 A 中盡可能多的將電量轉移到電容 B ,轉移不會有電量損失,如果能夠充滿 B 的最大容量,那剩余的電量仍然會留在 A 中。

現在已知有兩個電容,其最大容量分別為 a 和 b,其初始狀態都是電量值為 0,希望通過一些列的操作可以使其中某個電容(無所謂哪一個)中的電量值等于 c (c也是正整數),這一些列操作所用的最少指令條數記為 M,如果無論如何操作,都不可能完成,則定義此時 M = 0。

顯然對于每一組確定的 a,b,c,一定會有一個 M 與之對應。

這里需要輸入的是 a、b、c ,給出兩個樣例,例如 a = 3, b = 4, c = 2 ,則最少需要 4 個指令完成。


解釋:設最大容量為 3 的是 A 號電容,另一個是 B 號電容,對應的操作是 (充電 A)=> (轉移 A -> B) => (充電 A)=> (轉移 A -> B) ,這樣 A 就是目標的 2 電量。

第二個樣例 a = 2, b = 3, c = 4,由于 a 和 b 都無法到目標電量 4,所以輸出 0 代表無解。

這道題我們拿到以后,第一反應就是模擬三個指令,然后使用 BFS 廣度優先搜索來搜出答案,只要任意情況到達目標的 c 值就停下來。但是題目中給出了數據量 0 < a, b, c < 10^9 ,這個數據量約束了我們無法使用暴力搜索來求解。

簡要分析

首先從筆試的角度來分析,由于筆試時會有數據范圍的測試,這道題給出的數據范圍大概是這樣:

0?c?10^0?c?10^0?c?10^

所以如果沒有任何的思路和數論基礎,我建議使用 BFS 直接寫一版暴力,最少可以通過 > 50% 的數據,從而拿到一定的分數。(其實這就是 OI 得分賽制,沒有思路先暴力搶分)。

下面我們來分情況討論這個問題:

情況一

樣例已經給出了一種邊界情況,即當 c > max(a, b) ,這種情況是無法使得 A 和 B 的電量達到 c 的。直接輸出 0。

情況二

還有一種我們可以直接想到的情況,當 a = c 或者 b = c 的時候,只進行一次充電操作就可以完成,直接輸出 1。

情況三

接下來我們考慮一般情況,即需要滿足以下前提條件:

我們將這個問題換一個思路轉化一下假設給出的 a 、b、 c 一定有解,那么我們來設置對 A 做了 x 次的充(放)電,對 B 做了 y 次的充(放)電,并且做了 k 次的操作三。如果將 A、B 當做一個大電容來看這個電容只有充放電 a 單位、充放電 b 單位這 4 種操作。那么我們就可以列出一個關系式:

由于 a、b 為非負整數,又因為前提條件 c < max(a, b) ,則 x 和 y 符號相反。

暫且,我們先不管做了幾次操作三,先只考慮充放電問題,那其實就是已知 a、b、c,我們在給定范圍內求解 x 和 y 的解就可以了。那么這個問題我們要如何求解呢?這就是擴展歐幾里得算法所要解決的問題

擴展歐幾里得算法(Extended Euclidean)

帶 * 的章節略有難度。如果是從解決問題的工程角度出發,可以跳過證明直接記結論。

在推導上述問題的求解算法之前,我們需要先了解以下幾個概念知識。

丟番圖方程(Diophantine Equation)

丟番圖方程指的是:未知數個數多于方程個數,且未知數只能是整數的整數系數方程或方程組。例如以下式中,a、b、c 都為整數:

關于代數學鼻祖丟番圖(Diophantus)除了有《算數》這本開山巨作之外,還有一個好玩的數學題目墓志銘,有興趣可以自己了解。

裴蜀定理(Bézout's identity)

在數論中,裴蜀定理是一個關于最大公約數的定理。這個定理說明了對于任意整數 a、b 和他們的最大公約數 d,關于未知數 x 和 y 的線性丟番圖方程:

有解,當且僅當 m 是 d 的倍數時。這個等式也被稱為裴蜀等式。

裴蜀等式有解時必然有無窮多個整數解,每組解 x 、y 都稱之為裴蜀數,可用輾轉相除法求得。

輾轉相除法實現擴展歐幾里得算法

既然說可以用輾轉相除法來解決這個問題,那么我們先來說明一下如何通過輾轉相除法來求二元一次線性丟番圖方程。

輾轉相除法過程

以 23x + 17y = 1 為例,我們來求 GCD(23, 17):

改寫成余數形式

將等式右邊的第一項移項:

反向帶入原式

帶下劃線的 6 和 5 會使用 (1) 和 (2) 兩個式子反向帶入,形同換元:

所以反解得,x = 3, y = -4 是上述二元一次線性丟番圖方程的一組解。

* 擴展歐幾里得算法證明

來觀察一下輾轉相除法的最后兩個式子,終止條件是:

當且僅當第二個式子為 0 的時候停止這個遞歸運算。如何延伸到一般情況呢?我們將待求變量設為字母來嘗試一下。假設此時,我們要求 an 和 bn 為系數的二元一次線性丟番圖方程的系數,即待求方程:

根據上述的改寫余數形式,我們可以列出式一(| 是整除的意思):

假設未到達最終的終止條件,則有:

第二個式子中我們可以發現:

同理,第 n 個式子中有:

根據輾轉相除的規則,我們知道第 0 項中 b = 0、 a = 1 ,而我們要求的是第 n 項中的 a 和 b,所以可以通過 a 和 b 的遞推公式逐一推導而來。

如此我們證明了 an 和 bn 的遞推關系,下面我們來證明 xn 的遞推關系。

由上文證得了:

我們將其帶入到第一個式子中:

所以可以求得:

由于輾轉相除的推論我們可得:

所以:

即:

代碼實現擴展歐幾里得算法

為了實現上述的反向帶入原式的過程,我們通過遞歸遞歸到最深的一層,將每一層的解帶入即可完成最終的求解:

# pythondef ex_gcd(a, b): if b == 0: return 1, 0, a else: x, y, r = ex_gcd(b, a % b) x, y = y, (x - (a // b) * y) return x, y, r// c++int ex_gcd(int a, int b, int &x, int &y) { if(b == 0) { x = 1; y = 0; return a; } int r = ex_gcd(b, a % b, x, y); int t = y; y = x - (a / b) * y; x = t; return r;}

但是我們注意到,由于裴蜀定理,我們求解的丟番圖方程中,等號右邊的常數必須是 k * gcd(a, b)。所以我們的求解其實是:

所以通過擴展 GCD 算法求得的 x0 和 y0 這組解,并不是我們要求的最終解。同樣的,我們對其擴大 k 倍就是我們想要對結果:

小結

有了這些知識,你對那道“地獄難度”的頭條面試題有沒有更多的想法呢?這里有一道 [LeetCode-365] 水壺問題 你可以嘗試一下,做完之后想必會對擴展 GCD 算法有更深的理解。

至于頭條面試題,我將在下一篇文繼續講述并代碼實現此題的解法。

總結

以上是生活随笔為你收集整理的如何利用扩展欧几里得算法求解不定方程_客户端不用的算法系列:从头条笔试题认识扩展欧几里得算法...的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 中文字幕乱轮 | 99产精品成人啪免费网站 | 久久久久久av | 怎么可能高潮了就结束漫画 | 亚洲精品乱码久久久久久麻豆不卡 | 国产色无码精品视频国产 | av看片资源 | 欧美精品第一区 | 无码人妻一区二区三区线 | 精品日韩在线观看 | 91小仙女jk白丝袜呻吟 | 最新黄网| www.香蕉视频在线观看 | 久久久精品久久久久久 | 国产一区二区三区在线视频 | 久久精品人人爽 | 一区二区三区欧美精品 | 91国偷自产一区二区三区老熟女 | 久久久一区二区三区四区 | 秘密的基地 | 久久精品国产大片免费观看 | 黄色一区二区三区四区 | 五月婷婷深深爱 | 欧美性猛交xx乱大交 | 国产精品人人妻人人爽人人牛 | 国产成人综合自拍 | 黄色一毛片 | 日本久久久久久 | 国产又粗又黄的视频 | 日本69av| 国产精品一级二级 | 国产精品成人一区二区三区电影毛片 | 97福利社 | 国产情侣露脸自拍 | 初音未来打屁股 | 中国吞精videos露脸 | 欧美福利视频在线 | 香蕉在线视频播放 | 青青草视频在线看 | 成人激情视频在线 | 黄网站在线免费看 | 欧美色图在线视频 | 手机免费看av | 久久久久亚洲av无码专区桃色 | 欧美三级手机在线观看 | 久久成人福利视频 | 亚洲网av| 国产强伦人妻毛片 | 国产乱码一区二区三区在线观看 | 久草五月| 日韩精品一区二区三区 | 国产美女视频91 | 欧美乱妇狂野欧美在线视频 | 欧美 丝袜 自拍 制服 另类 | 久久久久久久久蜜桃 | 国产不卡一区 | 亚洲一区a | 日韩国产精品一区二区三区 | 久久97精品久久久久久久不卡 | 人妻少妇无码精品视频区 | 老熟妇仑乱视频一区二区 | 国产无套精品一区二区三区 | 一区二区三区蜜桃 | 婷婷色九月 | 91久久精品国产91性色69 | 夜夜爽www | 欧美精品免费在线 | 国产免费一级片 | 无码人妻一区二区三区精品视频 | 国产精品女人久久久 | 美女精品网站 | 伊人网成人| 免费黄色小网站 | www.日日日| 91高清在线视频 | 禁断介护av | 久草欧美 | 日韩精品麻豆 | 风间由美在线观看 | 日韩欧美91 | 亚洲熟妇一区二区 | 老色批永久免费网站www | 久久国产激情视频 | 毛片网站在线看 | 亚洲精品无码专区 | 免费看黄色漫画 | 印度午夜性春猛xxx交 | 日皮在线观看 | 日本污视频在线观看 | 亚洲情涩| 天天操穴| 精品黑人一区二区三区在线观看 | 理论在线视频 | 久草视频这里只有精品 | 人人射人人爱 | 亚洲精选91 | 亚欧美精品| 亚洲成人网页 | 欧美中文一区 |