【算法日记】大整数乘法分支递归实现

   日期:2020-09-25     浏览:91    评论:0    
核心提示:问题描述:如标题所示,就是两个大整数相乘,有时候如果数值过大,计算机是不能直接计算出来的,就需要使用到分支的思想。分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同。求出子问题的解,就可得到原问题的解。即一种分目标完成程序算法,一般情况都会用二分来解决(网上资料很多,此处不再赘述)。情景假设:假设有两个大整数X、Y,分别设X=1234、Y=6789。现在要求X*Y的乘积,小学的算法就是把X与Y中的每一项去乘,但是这样的乘法所需的时间复杂度为O(N^2

问题描述:如标题所示,就是两个大整数相乘,有时候如果数值过大,计算机是不能直接计算出来的,就需要使用到分支的思想。
分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同。求出子问题的解,就可得到原问题的解。即一种分目标完成程序算法,一般情况都会用二分来解决(网上资料很多,此处不再赘述)。
情景假设:假设有两个大整数X、Y,分别设X=1234、Y=6789。现在要求X*Y的乘积,小学的算法就是把X与Y中的每一项去乘,但是这样的乘法所需的时间复杂度为O(N^2),(因为每一位要逐个去乘),所以效率比较低下。那我们可以采用分治的算法,将X、Y拆分成四部分,如下图:

这样X可以表示为
Y同理,所以Y=C*10^(n/2)+D;
(有的资料书上写的是X=A**2^(n/2)+B,因为它是表示的二进制,此处写的是十进制。)
所以现在将一个大的整数分成了两部分,问题规模减小,这样直接相乘就会写成
但是这样你会发现,最后还是要计算4次n/2位整数的乘法,以及三次加法,根据master定理最后会发现T(n)=O(n^2);所以说这其实没有改进成功,要改进成功,就需要通过将算式变形来减少乘法的次数,对此,我们写成如下形式:
这样就能减少乘法的次数,(只做了AC,BD (A-B)(D-C)三次乘法),由master定理可得T(n)=O(n^log3),优化成功。
测试代码如下:


#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_s("%d%d%d", &x, &y, &n);
	printf("x 和 y的乘积为:%d", divideConquer(x, y, n));
}
 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服