分治法求解大整数相乘问题
【问题描述】 设X和Y都是n位的大整数,现在要计算它们的乘积XY。
【提示】采用分治法求解两个十进制大整数的乘法,以提高乘法的效率,减少乘法次数。
计算公式为:
XY=AC10n+[(A-B)(D-C)+AC+BD]10n/2+BD
下面的例子演示了分治算法的计算过程。
设X=314l,Y=5327,用上述算法计算XY的计算过程可列表如下,其中带’号的数值是在计算完成AC,BD,和(A-B)(D-C)之后才填入的。
X=3141 A=31 B=41 A-B=-10
Y=5327 C=53 D=27 D-C=-26
AC=(1643)’
BD=(1107)’
(A-B)(D-C)=(260)’
XY=(1643)‘104+[(1643)’+(260)‘+(1107)’]102+(1107)’
=(16732107)’
A=31 A1=3 B1=1 A1-B1=2
C=53 C1=5 D1=3 D1-C1=-2
A1C1=15 B1D1=3 (A1-B1)(D1-C1)=-4
AC=1500+(15+3-4)10+3=1643
B=41 A2=4 B2=1 A2-B2=3
D=27 C2=2 D2=7 D2-C2=5
A2C2=8 B2D2=7 (A2-B2)(D2-C2)=15
BD=800+(8+7+15)10+7=1107
|A-B|=10 A3=1 B3=0 A3-B3=1
|D-C|=26 C3=2 D3=6 D3-C3=4
A3C3=2 B3D3=0 (A3-B3)(D3-C3)=4
(A-B)(D-C)=200+(2+0+4)10+0=260
【算法时间复杂度分析】
该算法仅需做3次n/2位整数的乘法(AC,BD和(A-B)(D-C)),6次加、减法和2次移位的运算。所以,该算法时间复杂度为:
T(n)=O(nlog3)=O(n1.59)
//代码如下
/*
函数功能:分治法求两个N为的整数的乘积
输入参数:X,Y分别为两个N位整数
算法思想:
时间复杂度为:T(n)=O(nlog3)=O(n1.59)
*/
#include<iostream>
#include<math.h>
using namespace std;
#define SIGN(A) ((A > 0) ? 1 : -1)
int IntegerMultiply(int X, int Y, int N) //参数为大整数 X,Y及它们相同的位数 N
{
int sign = SIGN(X) * SIGN(Y); //确定两数乘积的正负
int x = abs(X); //将两数化为绝对值,之后计算再加入正负号
int y = abs(Y);
if((x == 0) || (y == 0)) //乘数有一个为 0,两数相乘为 0
return 0;
if (N == 1) //只剩一位时,返回
return sign * x * y;
else
{
int A = x / pow(10, N/2);
int B = x - A * pow(10, N/2);
int C = y / pow(10, N/2);
int D = y - C * pow(10, N/2);
int AC = IntegerMultiply(A, C, N/2);
int BD = IntegerMultiply(B, D, N/2);
int ADBC = IntegerMultiply(A - B, D - C, N/2) + AC + BD;
return sign * (AC * pow(10, N) + ADBC * pow(10, N/2) + BD); //可根据公式化简
}
}
int main()
{
int x, y, z, n = 0;
cin >> x >> y;
z = x;
while(z != 0) // 求 X,Y有多少位
{
z = z / 10;
++n;
}
cout << "x * y = " << IntegerMultiply(x, y, n) << endl;
cout << "x * y = " << x * y << endl;
return 0;
}