递归分治-大整数乘法
最近在学算法,想着不能只是学,要深刻领悟,需要记录,需要写代码,需要分析……所以就诞生了这篇博客。
问题描述:
设X和Y都是n位整数,计算它们的乘积XY。可以使用传统的数学计算方法,但是这样做计算步骤太多,效率较低。如果将每个一位数的乘法或加法看做一步运算,则这种方法需要进行O(n^2)步运算才能求出乘积XY。
方法一
基本计算步骤如下,如:56*78
第一步:6*8;
第二步:5*8;
第三步:6*7;
第四步:5*7;
第五步:以上4步的和加起来,得到最后的结果。
将以上的例子进行抽象,即可以这样表示:
将n位十进制(还包括其他进制,如二进制、八进制、十六进制等)整数X和Y都分为2段,每段的长为n/2位。即:
X=A∗10n2+BX={A*{10^{n\over2}}+B}
Y=C∗10n2+DY={C*{10^{n\over2}}+D}
这样XY的乘积就是
XY=(A∗10n2+B)∗(C∗10n2+D)=AC∗10n+(AD+BC)∗10n2+BDXY={(A*{10^{n\over2}}+B)}*{(C*{10^{n\over2}}+D)}=AC*10^n+(AD+BC)*{10^{n\over2}}+BD
由以上的等式我们可以看出,需要4次乘法,分别是:AC,AD,BC,BD,以及3次加法,还有3次移位操作。所有这些加法和移位公用O(n)步运算。设T(n)是2个n位整数相乘所需的运算总数,则有:
T(n) =
\begin{cases} O(1), & \text{$n$ =1} \\ 4T({n\over2})+O(n), & \text{ $n$>1} \end{cases}
然后,我们进行计算,得到该算法的时间复杂度为O(n^2),具体过程如下:
实现代码如下:
#include<stdio.h>
#include<math.h>
#define MAX_LENGTH 10
void sqperateNum(int num, int seArray_num[]); //数据存储到数组中
int main()
{int i=0, j=0;int num1, num2;int sum = 0;int seArray_num1[MAX_LENGTH] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; //初始化数组int seArray_num2[MAX_LENGTH] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; printf("Please input two numbers:\n");scanf("%d%d", &num1, &num2);sqperateNum(num1, seArray_num1);sqperateNum(num2, seArray_num2);while (seArray_num1[i]!=-1){while (seArray_num2[j] != -1){sum += seArray_num1[i] * seArray_num2[j] * pow(10.0, (i + j));j++;}i++;j = 0;}printf("%d*%d=%d\n", num1, num2, sum);return 0;
}
//数据存储到数组中
void sqperateNum(int num, int seArray_num[])
{int k = 0;do{seArray_num[k] = num % 10; num /= 10; k++;} while (num%10!=0 ||(num/10 !=0));
}
方法二
然后我们对于该问题进行优化,要想改进该算法的复杂性,必须减少乘法的次数。我们对以上的表达式进行一个优化,得到如下的表达式:
XY=(A∗10n2+B)(C∗10n2+D)=AC∗10n+(AD+BC)∗10n2+BD=AC∗10n+((A−B)(D−C)+AC+BD)∗10n2+BDXY=({A*{10^{n\over2}}+B})({C*{10^{n\over2}}+D})=AC*{10^{n}}+(AD+BC)*{10^{n\over2}}+BD = AC*{10^{n}}+((A-B)(D-C)+AC+BD)*{10^{n\over2}}+BD
通过以上表达式变形,我们只需进行3次n/2位整数的乘法,6次加减法操作和2次移位。由此可得如下的表达式:
T(n) =
\begin{cases} O(1), & \text{$n$ =1} \\ 3T({n\over2})+O(n), & \text{ $n$>1} \end{cases}
再次进行计算,得到该算法的时间复杂度为O (nlog3)({n^{log3}}),相比于O (n2)({n^{2}})来说,这是一个很大的改进。
代码如下,这个代码是在别人的基础上改了一下,具体如下:
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
int IntegerMultiply(int X, int Y, int N)
{int x = X;int y = Y;if ((0 == x) || (0 == y))return 0;if (1 == N){return x*y;}else{int XL = x / (int)pow(10., (int)N / 2);int XR = x - XL * (int)pow(10., N / 2);int YL = y / (int)pow(10., (int)N / 2);int YR = y - YL * (int)pow(10., N / 2);int XLYL = IntegerMultiply(XL, YL, N / 2);int XRYR = IntegerMultiply(XR, YR, N / 2);int XLYRXRYL = IntegerMultiply(XL - XR, YR - YL, N / 2) + XLYL + XRYR;return (XLYL * (int)pow(10., N) + XLYRXRYL * (int)pow(10., N / 2) + XRYR);}
}
int main()
{int x = 1234, y = 9876; int value = 0;value = IntegerMultiply(x, y, 4);printf("%ld*%ld=%ld", x,y,value);return 0;
}
综上所述,主要是掌握对算法复杂度的推导,以及实现相应的算法。在这里,不得不感叹数学家的厉害,只是一个小小的公式变换,就将复杂度大大降低了。请大数学家们收下我的膝盖,哈哈~
递归分治-大整数乘法相关推荐
- c++/c 大整数乘法的分治与递归实现(string存储)
c++/c 大整数乘法的分治与递归实现(string存储) 最基础的分治和递归实现,算是思路比较清晰但是较暴力的算法, 不多说,看代码,速度不快,但重要在思想与细节. #include<iost ...
- 【分治算法】大整数乘法
前言 最近开了算法导论课,上来就是递归分治,大整数乘法就是分治法的典型案例,通过参考网上书上我终于编程实现了大整数乘法,特此纪念 原理 由于两个大整数直接相乘太大,所以我们可以将它划分成几个小块分别相 ...
- 【分治】大整数乘法(C++)
刚发现个问题,,初学时竟然是使用的long型进行计算的,导致这篇文章虽展现了分治的想法,但并没有实际解决大整数乘法的计算问题. 仅供参考,日后再改 一.大整数乘法 一般计算方法 有n位大整数X和Y,计 ...
- 大整数乘法(递归+分治法)
目录 一.问题描述 二.思路分析 分治法介绍: 问题分析: 三.算法伪代码 四.代码实现效果 五.源代码 六.参考文章 一.问题描述 请设计一个有效的算法,可以进行两个n位大整数的乘法.(n=2^k, ...
- java 整数乘法的算法,大整数乘法——分治算法的时间复杂度
1.1原始的低效算法 我们将n位(为方便讨论简化问题,我们假设n是2的幂)十进制整数(二进制也可以)X.Y都分为2段,每段的长度是n/2位. 如果现在直接用递归或分治进行编程,其算法复杂度为: 其中: ...
- 【算法/C语言】大整数乘法(分治)
题目: 用分治算法编程实现两个n位十进制大整数的乘法运算. 思路: 参考大整数乘法的详解 伪码: Function MulOfLargeInt(X,Y,n)** 输入:n位乘数X,Y,位数n 输出:X ...
- 分治算法经典问题---大整数乘法(1~32位大整数乘法)C++
大整数乘法 大整数乘法(1~32位大整数乘法) 分治的思想 实验题目及要求(大整数乘法) 算法分析(result=m4*10^2^+(m2+m3)*10^n/2^+m1) 算法分析 代码 源文件 ma ...
- 分治法实验之大整数乘法(算法设计分析)
分治法实验之大整数乘法 01. 问题描述 02. 输入格式 03. 输出格式 04. 输入样例 05. 输出样例 06. 问题分析 07. 算法设计 08. 代码实现 09. 测试结果 10. 复杂度 ...
- PYTHON:大整数乘法(分治法)
何为分治法: 分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同.求出子问题的解,就可得到原问题的解.即一种分目标完成程序算法,简单问题可用二分法 ...
最新文章
- java获取map大小_java – 从HashMap获取最大Set大小
- Nand Flash数据存储单元的整体架构
- 离群点、异常点检测及Python实现(正态分布3∂,Z-score 异常值检测,基于MAD的Z-score 异常值检测,杠杆值点、DFFITS值、SR学生化残差、cook距离和covratio值)
- 潭州课堂25班:Ph201805201 第十二课 new方法,定制属性访问,描述符与装饰器 (课堂笔记)...
- 推荐一个高仿微信的项目 有点屌!!!
- CSS块元素与内联元素(转)
- 英特尔nuc能代替主机吗_拆了拆了!Intel NUC装机!小机箱退烧器啊!主机显示器合体...
- 《FLUENT 14流场分析自学手册》——2.3 FLUENT14.5软件包的安装以及运行
- php 到处excel 乱码,php 导出excel乱码怎么办
- Linux信号量常用操作表
- 数据结构 实验1——一元多项式的表示与相加
- 南京南汽技工学校计算机专业是啥,计算机中心附近技术类学校
- 1258:【例9.2】数字金字塔
- LinkedList入门教程
- 【Bug】无法访问Windows Installer服务
- AD如何快速更改元件库器件的颜色
- oracle视图无故消失,oracle数据库视图无效
- vue使用echarts来绘制中国地图下钻省市区县级地图
- 2008年中山市小学生信息学邀请赛第一题——机器人行走
- 女大学生第一次面试就入职美团,只因这份987页Java面试宝典,看完才发现,应届生求职也没那么难
热门文章
- 易语言lsp劫持_[原创]不用导出任何函数的DLL劫持注入,完美!
- 华硕Eee PC 设置U盘启动
- 小技巧助你解决div+css网页内容显示不完整
- 云服务器ecs增加带宽,老鸟告诉你云服务器带宽多少合适?
- 这可能是2021年GDPR的最大罚单
- iphone一键转移_苹果手机如何一键转移数据 转移教程介绍
- app卡在启动页面android,app启动一直停留在启动页面
- 前端---js中onmouseover和onmouseout事件
- pdf格式如何压缩大小?压缩pdf大小的方法?
- 在html中取消超链接的下划线