最近在学算法,想着不能只是学,要深刻领悟,需要记录,需要写代码,需要分析……所以就诞生了这篇博客。

问题描述:

设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) =

{O(1),4T(n2)+O(n),n =1 n>1

\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) =

{O(1),3T(n2)+O(n),n =1 n>1

\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;
}

综上所述,主要是掌握对算法复杂度的推导,以及实现相应的算法。在这里,不得不感叹数学家的厉害,只是一个小小的公式变换,就将复杂度大大降低了。请大数学家们收下我的膝盖,哈哈~

递归分治-大整数乘法相关推荐

  1. c++/c 大整数乘法的分治与递归实现(string存储)

    c++/c 大整数乘法的分治与递归实现(string存储) 最基础的分治和递归实现,算是思路比较清晰但是较暴力的算法, 不多说,看代码,速度不快,但重要在思想与细节. #include<iost ...

  2. 【分治算法】大整数乘法

    前言 最近开了算法导论课,上来就是递归分治,大整数乘法就是分治法的典型案例,通过参考网上书上我终于编程实现了大整数乘法,特此纪念 原理 由于两个大整数直接相乘太大,所以我们可以将它划分成几个小块分别相 ...

  3. 【分治】大整数乘法(C++)

    刚发现个问题,,初学时竟然是使用的long型进行计算的,导致这篇文章虽展现了分治的想法,但并没有实际解决大整数乘法的计算问题. 仅供参考,日后再改 一.大整数乘法 一般计算方法 有n位大整数X和Y,计 ...

  4. 大整数乘法(递归+分治法)

    目录 一.问题描述 二.思路分析 分治法介绍: 问题分析: 三.算法伪代码 四.代码实现效果 五.源代码 六.参考文章 一.问题描述 请设计一个有效的算法,可以进行两个n位大整数的乘法.(n=2^k, ...

  5. java 整数乘法的算法,大整数乘法——分治算法的时间复杂度

    1.1原始的低效算法 我们将n位(为方便讨论简化问题,我们假设n是2的幂)十进制整数(二进制也可以)X.Y都分为2段,每段的长度是n/2位. 如果现在直接用递归或分治进行编程,其算法复杂度为: 其中: ...

  6. 【算法/C语言】大整数乘法(分治)

    题目: 用分治算法编程实现两个n位十进制大整数的乘法运算. 思路: 参考大整数乘法的详解 伪码: Function MulOfLargeInt(X,Y,n)** 输入:n位乘数X,Y,位数n 输出:X ...

  7. 分治算法经典问题---大整数乘法(1~32位大整数乘法)C++

    大整数乘法 大整数乘法(1~32位大整数乘法) 分治的思想 实验题目及要求(大整数乘法) 算法分析(result=m4*10^2^+(m2+m3)*10^n/2^+m1) 算法分析 代码 源文件 ma ...

  8. 分治法实验之大整数乘法(算法设计分析)

    分治法实验之大整数乘法 01. 问题描述 02. 输入格式 03. 输出格式 04. 输入样例 05. 输出样例 06. 问题分析 07. 算法设计 08. 代码实现 09. 测试结果 10. 复杂度 ...

  9. PYTHON:大整数乘法(分治法)

    何为分治法: 分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同.求出子问题的解,就可得到原问题的解.即一种分目标完成程序算法,简单问题可用二分法 ...

最新文章

  1. java获取map大小_java – 从HashMap获取最大Set大小
  2. Nand Flash数据存储单元的整体架构
  3. 离群点、异常点检测及Python实现(正态分布3∂,Z-score 异常值检测,基于MAD的Z-score 异常值检测,杠杆值点、DFFITS值、SR学生化残差、cook距离和covratio值)
  4. 潭州课堂25班:Ph201805201 第十二课 new方法,定制属性访问,描述符与装饰器 (课堂笔记)...
  5. 推荐一个高仿微信的项目 有点屌!!!
  6. CSS块元素与内联元素(转)
  7. 英特尔nuc能代替主机吗_拆了拆了!Intel NUC装机!小机箱退烧器啊!主机显示器合体...
  8. 《FLUENT 14流场分析自学手册》——2.3 FLUENT14.5软件包的安装以及运行
  9. php 到处excel 乱码,php 导出excel乱码怎么办
  10. Linux信号量常用操作表
  11. 数据结构 实验1——一元多项式的表示与相加
  12. 南京南汽技工学校计算机专业是啥,计算机中心附近技术类学校
  13. 1258:【例9.2】数字金字塔
  14. LinkedList入门教程
  15. 【Bug】无法访问Windows Installer服务
  16. AD如何快速更改元件库器件的颜色
  17. oracle视图无故消失,oracle数据库视图无效
  18. vue使用echarts来绘制中国地图下钻省市区县级地图
  19. 2008年中山市小学生信息学邀请赛第一题——机器人行走
  20. 女大学生第一次面试就入职美团,只因这份987页Java面试宝典,看完才发现,应届生求职也没那么难

热门文章

  1. 易语言lsp劫持_[原创]不用导出任何函数的DLL劫持注入,完美!
  2. 华硕Eee PC 设置U盘启动
  3. 小技巧助你解决div+css网页内容显示不完整
  4. 云服务器ecs增加带宽,老鸟告诉你云服务器带宽多少合适?
  5. 这可能是2021年GDPR的最大罚单
  6. iphone一键转移_苹果手机如何一键转移数据 转移教程介绍
  7. app卡在启动页面android,app启动一直停留在启动页面
  8. 前端---js中onmouseover和onmouseout事件
  9. pdf格式如何压缩大小?压缩pdf大小的方法?
  10. 在html中取消超链接的下划线