分治法的經典問題 大整數相乘

2021-07-25 03:30:07 字數 2196 閱讀 5241

討論問題時,先來了解一下什麼是分治法。

分治法的意思就是,分而治之,也就是把乙個問題,拆分成幾個小問題,最後再彙總解決的方法

假如現在我們要求兩個大整數相乘的乘積,如1234 * 1234(這裡為了了分析簡便,所以不舉形如1234567891234567這樣的大整數,不必要在此糾結),那麼按照我們小學學的乘法,就是用乘數的每一項去和1234相乘,這樣很明顯,演算法的時間複雜度是o(n^2),效率很低下,那麼有沒有一種更好的方式?我們可以使用分治法來解決。

首先將x和y分成a,b,c,d

此時將x和y的乘積轉化為圖中的式子,把問題轉化為求解式子的值

看起來好像有點變化,分析一下:對這個式子,我們一共要進行4次 n / 2的乘法(ac2次, ad, bc)和 3次加法,因而該演算法的時間複雜度為:

t(n) = 4 * t(n / 2) + θ(n)

通過master定理可以求得 t(n) = θ(n ^ 2),跟小學演算法的時間複雜度沒有區別。

但是我們再來看看,我們是否可以用加法來換取乘法?因為多乙個加法操作,也是常數項,對時間複雜度沒有影響,如果減少乙個乘法則不同。

xy=ac2^n+[(a-b)(d-c)+ac+bd]2^n/2+bd

現在的時間複雜度為:

t(n) = 3 * t(n / 2) + θ(n),通過master定理求得,t(n) = o(n^log2(3) ) = o(n^1.59 )。

master定理例項:

對x = 1234 和 y = 5678來分析:

divideconquer(1234, 5678, 4)

————————————————————————

x=1234 | a=12 | b=34 | a-b=-22

y=5678 | c=56 | d=78 | d-c=22

三次遞迴:

ac = divideconquer(12, 56, 2)

bd = divideconquer(34, 78, 2)

(a-b)(d-c) = divideconquer(-22, 22, 2)

ac遞迴

————————————————————————

x=12 | a1=1 | b1=2 | a1-b1=-1

y=56 | c1=5 | d1=6 | d1-c1=1

a1*c1 = divideconquer(1, 5, 1) = 5

b1*d1 = divideconquer(2, 6, 1) = 12

(a1-b1) * (d1-c1) = divideconquer(-1, 1, 1) = -1;

所以ac遞迴求得的值為:5 * 10 ^ 2 + (-1 + 5 + 12)* 10 + 12 = 672

同理可得 bd = 2652 和 (a-b)(d-c) = -484

最終可得 x * y = 7006652

#include

#include

using

namespace

std;

#define sign(a) ((a > 0) ? 1 : -1)

int divideconquer(int x, int y, int n)else

if(n == 1)else

}int main()

結果:

分治法 大整數相乘

大整數相乘 a b兩個整數,a有n位 123456 n b有m位 123456 m 一般的思路是像最初學習乘法時一樣逐位相乘後相加,但是這樣做演算法的複雜度過高,但這仍然是解題的基本思想。既然提到分治,那麼如何分,怎麼治?能夠找到乙個大問題劃分為小問題方法的重要技巧是能夠看到大問題的規模和所謂規模的...

分治法求解大整數相乘問題

問題描述 設x和y都是n位的大整數,現在要計算它們的乘積xy。提示 採用分治法求解兩個十進位製大整數的乘法,以提高乘法的效率,減少乘法次數。計算公式為 xy ac10n a b d c ac bd 10n 2 bd 下面的例子演示了分治演算法的計算過程。設x 314l,y 5327,用上述演算法計算...

大整數相乘 分治法(JS)

相乘的基本原理 如 1234 567第一步 分解 234 12 和 34 567 5 和 67 第二步 分別計算 首部 12 5 60 中部 12 67 34 5 974 尾部 34 67 2278第三步 進製 因為是以兩位數字分割的,所以進製是滿100進一位 尾部 留78,進22,即78 中部 9...