遞迴與分治之大整數乘法

薛貓顎的腚發表於2020-11-25

大整數乘法

現在我們給出兩個數字1234和4321(這兩個數字並不大,以此為例而已),按照我們做乘法的習慣,我們寫成豎式,用1234分別跟4,3,2,1相乘並對應移位相加得到結果,那麼我們在這個過程中用了幾次乘法呢?是4次?不,其實1234跟4相乘是1,2,3,4分別乘4,也是4次乘法,因此一共我們使用了4*4次乘法。

這僅僅是4位,如果是更多,那麼演算法的複雜度無疑是O(n^2),為了提高效率,降低這種複雜度,我們可以使用分治法。

首先,我們將兩個n位大整數X,Y分開,分為四個n/2位的整數,如下:
在這裡插入圖片描述
例如,X=12345678,分成a=123410^4,b=56781;此時的計算效率如下:
在這裡插入圖片描述
利用我們學過的複雜度分析法,其複雜度如下:
在這裡插入圖片描述
根據master定理,複雜度為O(n^2),並沒有改進。

為了降低複雜度,我們必須用加法代替乘法,因此我們修改一下上面式子的形式:
在這裡插入圖片描述
在這裡插入圖片描述
補充:master定理:

在這裡插入圖片描述
程式碼摘自:https://blog.csdn.net/jeffleo/article/details/53446095

#include<cstdio>
#include<cmath>

using namespace std;

#define SIGN(A) ((A > 0) ? 1 : -1) 
int divideConquer(int X, int Y, int n){
    int sign = SIGN(X) * SIGN(Y);
    int x = abs(X);
    int y = abs(Y);
    if(x == 0 || y == 0){
        return 0;
    }else if(n == 1){
        return sign * x * y;
    }else{
        int A = (int) x / pow(10, (int)(n / 2));
        int B = x - A * pow(10, n / 2);
        int C = (int) y / pow(10, (int)(n / 2));
        int D = y - C * pow(10, n / 2);
        int AC = divideConquer(A, C, n / 2);
        int BD = divideConquer(B, D, n / 2);
        int ABDC = divideConquer((A - B), (D - C), n / 2) + AC + BD;
        return sign * (AC * pow(10 , n) + ABDC * pow(10, (int)(n / 2)) + BD); 
    }
}

int main(){
    int x, y, n;
    scanf("%d%d%d", &x, &y, &n);
    printf("x 和 y的乘積為:%d", divideConquer(x, y, n));
}

相關文章