閱讀467 返回首頁    go 阿裏雲 go 技術社區[雲棲]


2012 藍橋杯【初賽試題】大數乘法

大數乘法

對於32位字長的機器,大約超過20億,用int類型就無法表示了,我們可以選擇int64類型,但無論怎樣擴展,固定的整數類型總是有表達的極限!如果對超級大整數進行精確運算呢?一個簡單的辦法是:僅僅使用現有類型,但是把大整數的運算化解為若幹小整數的運算,即所謂:“分塊法”。

如圖【1.jpg】表示了分塊乘法的原理。可以把大數分成多段(此處為2段)小數,然後用小數的多次運算組合表示一個大數。可以根據int的承載能力規定小塊的大小,比如要把int分成2段,則小塊可取10000為上限值。注意,小塊在進行縱向累加後,需要進行進位校正。

以下代碼示意了分塊乘法的原理(乘數、被乘數都分為2段)。

 

#include <stdio.h>

#include <iostream>

using namespace std;

 

void bigmul(int x, int y, int r[])

{

    int base = 10000;

    int x2 = x / base;

    int x1 = x % base;

    int y2 = y / base;

    int y1 = y % base;

 

    int n1 = x1 * y1;

    int n2 = x1 * y2;

    int n3 = x2 * y1;

    int n4 = x2 * y2;

 

    r[3] = n1 % base;

    r[2] = n1 / base + n2 % base + n3 % base;

    --------------- // 填空

    r[0] = n4 / base;

 

     ---------------  //填空

    r[2] = r[2] % base;

    r[0] += r[1] / base;

    r[1] = r[1] % base;

}

int main(int argc, char* argv[])

{

    int x[] = {0,0,0,0};

    bigmul(87654321, 12345678, x);

    printf("%d%d%d%d\n", x[0],x[1],x[2],x[3]);

    system("pause");

    return 0;

}

 

 

 

解題思路:

不算難,就是類似平時乘法運算中的進位

按照它的算法,99*99應該是這個樣子

 

99*99正常方法:

 99

x99

---------

  891

891

---------

9801

 

99*99用題中敘述的方法:

 99

x99

---------

       81

    81

    81

 81

---------

 9  8  0 1

 

假設9為r[0],8、0、1分別是r[1]、r[2]、r[3],四個81分別是n1,n2、n3、n4。

則r[3]=n1%10;

r[2]=n1/10+n2%10+n3%10;

r[1]=n4%10+n2/10+n3/10;

r[0]=n4/10;

得到了上麵的一組結果,很容易就推出了空格1,空格二就是簡單的進位加減了,嘿嘿,分值到手!

 

#include <stdio.h>
#include <iostream>
using namespace std;

void bigmul(int x, int y, int r[])
{
    int base = 10000;
    int x2 = x / base;
    int x1 = x % base;
    int y2 = y / base;
    int y1 = y % base;

    int n1 = x1 * y1;
    int n2 = x1 * y2;
    int n3 = x2 * y1;
    int n4 = x2 * y2;

    r[3] = n1 % base;//取最後一位 
    r[2] = n1 / base + n2 % base + n3 % base;//取倒數第二位(n1的首和n2、n3的尾相加) 
    r[1] = n2 / base + n3 / base + n4 % base; //取倒數第三位(n2、n3的首與n4的尾相加) 
    r[0] = n4 / base;//取n4的首 

    r[1] += r[2] / base;  // r[1]要加上後麵進位的數 
    r[2] = r[2] % base;//隻取進位後的餘數 
    r[0] += r[1] / base;//r[0]要加上後麵進位的數 
    r[1] = r[1] % base;//隻取進位後的餘數 
    //r[3]沒有做任何加減,所以不需要進位也不需要加任何一位進的位數 
}
int main(int argc, char* argv[])
{
    int x[] = {0,0,0,0};
    bigmul(87654321, 12345678, x);
    printf("%d%d%d%d\n", x[0],x[1],x[2],x[3]);
    system("pause");
    return 0;
}


 

最後更新:2017-04-03 12:55:32

  上一篇:go 調試程序執行流程的小技巧
  下一篇:go WIKIOI-1098 均分紙牌