大整数乘法-分治算法
Posted xxmmqg
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了大整数乘法-分治算法相关的知识,希望对你有一定的参考价值。
分治算法思想
将问题分为k个子问题,对这k个子问题分别求解。如果子问题的规模仍然不够小,则每个子问题再划分为k个子问题,如此递归的进行下去,直到问题规模足够小,很容易求出其解为止。
问题分析
这个问题的时间复杂度我似懂非懂,想知道其中的具体过程的请自行百度。
对于两个数字X、Y,传统计算方式的时间复杂度是O(n^2)
。
那么我们可以根据高位低位进行分隔,例如:
其中,xn0
、xn1
分别为A、B的位数,yn0
、yn1
同理。那么X*Y
可写成如下结果:
[egin{align}
X*Y &= (A*10^{xn1}+B)(C*10^{yn1}+D) &= AC*10^{xn1+yn1}+AD*10^{xn1}+BC*10^{yn1}+BD
end{align}
]
由于我们需要计算4次大整数乘积,所以算法复杂度依然时O(n^2)
。
为了减小时间复杂度,我们进行如下改动:
令:
[ABCD = (A*10^{xn1}-B)(D-C*10^{yn1})
]
展开可得:
[ABCD = AD*10^{xn1}-AC*10^{xn1+yn1}-BD+BC*10^{yn1}
]
综上可得:
[X*Y = ABCD+2AC*10^{xn1+yn1}+2BD
]
现在我们将时间复杂度降低到了O(n^1.59)
。
C++代码
#include<iostream>
#include<cmath>
typedef long long ll;
using namespace std;
void AcceptAndCompute();
int SizeNumber(ll num);
ll Compute(ll X, ll Y, int xn, int yn);
int Sign(ll x);
int main()
{
AcceptAndCompute();
return 0;
}
void AcceptAndCompute()
{
ll X, Y;
cout<<"输入X,Y的值:"<<endl;
cout<<"X: "; cin>>X;
cout<<"Y: "; cin>>Y;
cout<<"直接计算结果:"<<X*Y<<endl; // 直接运算
int xn, yn;
xn = SizeNumber(abs(X));
yn = SizeNumber(abs(Y));
int sign_x, sign_y;
sign_x = Sign(X);
sign_y = Sign(Y);
X = abs(X); Y = abs(Y);
cout<<"分治计算结果:"<<ll(Compute(X, Y, xn, yn)*sign_x*sign_y)<<endl;
}
int SizeNumber(ll num) // 计算num有多少位
{
return int(log10(num)) + 1;
}
int Sign(ll x) // 获取符号
{
return x > 0 ? 1 : -1;
}
ll Compute(ll X, ll Y, int xn, int yn)
{
if(!X || !Y) return 0;
if(xn == 1 || yn == 1) return X * Y;
int xn0 = xn / 2, yn0 = yn / 2;
int xn1 = xn - xn0, yn1 = yn - yn0;
ll A = ll(X / ll(pow(10, xn1)));
ll B = ll(X % ll(pow(10, xn1)));
ll C = ll(Y / ll(pow(10, yn1)));
ll D = ll(Y % ll(pow(10, yn1)));
ll AC = Compute(A, C, xn0, yn0);
ll BD = Compute(B, D, xn1, yn1);
ll ABCD = Compute(ll(A*pow(10,xn1)-B), ll(D-C*pow(10, yn1)), xn0, yn0);
return ll(2*AC*pow(10, (xn1+yn1))+ABCD+2*BD);
}
感谢
以上是关于大整数乘法-分治算法的主要内容,如果未能解决你的问题,请参考以下文章