分治算法:分治算法由两部分组成,分和治,分是使问题规模变小,递归解决较小的问题,治是从子问题的解中构建原问题的解。
传统上,在正文中至少含有两个递归调用的例程叫做分治算法,而正文中只含有一个递归调用的例程不是分治算法。
我们一般坚持子问题是不相交的。
在前面写的归并排序和快速排序就是分治算法的一种例程。
所有有效的分治算法都是把问题分成一些子问题,每个子问题都是原问题的一部分,然后进行某些附加的工作,以算出最后的答案。

分治算法解决大整数相乘。
如果X = 61438521,而Y = 94736407,那么XY = 5820464730934047
如果把x和y拆成两半,分别由最高几位和最低几位数字组成。
XL = 6143,XR = 8521,YL=9473,YR = 6407.

则 X = XL10⁴ +XR,Y = YL10⁴ + YR。
则 XY = XLYL10⁸ + YL10⁴XR + XL10⁴YR + XRYR
则 XY = XLYL
10⁸ + (XRYL+XLYR)10⁴+ XRYR
则 XY = XLYL*10⁸ + ((XL+XR)(YR+YL)-XLYL-XRYR)10⁴+ XRYR
则 XY可以由3次乘法组成,即 XLYL,XRYR,(XL+XR)
(YR+YL)
它们每一个都是原来问题大小的一半(N/2),10⁸和10⁴作乘法实际就是添加一些0。

核心算法

string multiply(string &x, string &y) {bool flag = false;                       //最终结果的正负号,0为正号,1为负号if (x.at(0) == '-' && y.at(0) !='-' || x.at(0) != '-' && y.at(0) == '-') {//一正一负,最终符号为负flag = true;}if (x.at(0) == '-') {      //去除负号x = x.substr(1);}if (y.at(0) == '-') {//去除负号y = y.substr(1);}int init_len = 4;if (x.length() > 2 || y.length() > 2) { // 长度大于2时,最小长度应该为4,故初始值为4if (x.length() >= y.length()) {while (init_len < x.length())init_len *= 2; //计算两个数最终的长度//添加前置0if (x.length() != init_len) {addPreZero(x, init_len - x.length());}addPreZero(y, init_len - y.length());}else {while (init_len < y.length())init_len *= 2;//添加前置0addPreZero(x, init_len - x.length());if (y.length() != init_len) {addPreZero(y, init_len - y.length());}}}int n = x.length();string result;if (n <= 2) { //长度为2时,结束递归int x1 = strToInt(x);int y1 = strToInt(y);int z = x1 * y1;result = intToStr(z);}else {string xl, xr, yl, yr;xl = x.substr(0, n / 2);xr = x.substr(n / 2, n);yl = y.substr(0, n / 2);yr = y.substr(n / 2, n);string xlyl = multiply(xl, yl);string xryr = multiply(xr, yr);string xlAddXr = add(xl, xr);string ylAddYr = add(yl, yr);string t = add(xlyl, xryr);string t1 = multiply(xlAddXr, ylAddYr);string t2 = subtract(t1, t);addLastZero(t2, n / 2);addLastZero(xlyl, n);result = add(add(t2, xlyl), xryr);}if (flag) { //结果为负数result.insert(0, "-");}return result;
}

其它函数

#include <iostream>
#include <malloc.h>
#include <algorithm>
#include <sstream>
using namespace std;int strToInt(string k) {//string字符串变整数型int back;stringstream instr(k);instr >> back;return back;
}
string intToStr(int intValue) {string result;stringstream stream;stream << intValue;//将int输入流stream >> result;//从stream中抽取前面放入的int值return result;
}
void removePreZero(string &str) {//去掉前置0,需要考虑只有一个0或者全部是0的情况if (str.length() == 1)return;int k = 0;for (int i = 0; i < str.length(); i++) {if (str.at(i) == '0') {k++;}else {break;}}if (k == str.length())str = "0";else {str = str.substr(k);}
}
//大数相加,不考虑前置0的情况
string add(string x, string y) {string result = "";//去掉前置0removePreZero(x);removePreZero(y);//反转字符串方便相加reverse(x.begin(), x.end());reverse(y.begin(), y.end());for (int i = 0, j = 0; j || i < max(y.length(), x.length()); i++) {int t = j;if (i < x.length())t += (x.at(i) - '0');if (i < y.length())t += (y.at(i) - '0');int q = t % 10;result.insert(0, intToStr(q));j = t / 10;}return result;
}
string subtract(string &x, string &y) {string result = "";//去掉前置0removePreZero(x);removePreZero(y);int len_x = x.length();int len_y = y.length();int len = len_x > len_y ? len_x : len_y;int *tempResult = (int *)malloc(sizeof(int) * len);string sign;if (len_x > len_y) {// x - y为正数sign = "+";}else if (len_x < len_y) { //x-y为负数sign = "-";}else { //长度相同则判断各位的大小int i;for (i = 0; i < len_x; i++) {if (x.at(i) == y.at(i))continue;else if (x.at(i) > y.at(i)) {sign = "+";break;}else {sign = "-";break;}}//说明没有break,说明x == yif (i == len_x) {return "0";}}//反转字符串方便相减reverse(x.begin(), x.end());reverse(y.begin(), y.end());int q = 0;//若x大,则直接相减,否则用y-x,并且最终加上负号for (int i = 0; i < len; i++) {int aint = i < len_x ? x.at(i) - '0' : 0;int bint = i < len_y ? y.at(i) - '0' : 0;if (sign.at(0) == '+') {tempResult[q++] = aint - bint;}else {tempResult[q++] = bint - aint;}}for (int i = 0; i < q; i++) {if (tempResult[i] < 0) {tempResult[i + 1] -= 1;tempResult[i] += 10;}}q--;while (tempResult[q] == 0)q--;for (int i = q; i >= 0; i--) {result += intToStr(tempResult[i]);}if (sign.at(0) == '-')return sign + result;return result;
}
//添加前置0
void addPreZero(string &str, int zero_num) {for (int i = 0; i < zero_num; i++)str.insert(0, "0");
}
//添加后置0
void addLastZero(string &str, int zero_num) {for (int i = 0; i < zero_num; i++)str += "0";
}

第十章分治算法(大数相乘)相关推荐

  1. POJ1001 求高精度幂 (分治高精度大数相乘)

    总体思路: 高精度大数乘法 需要记录小数点位置 需要使用大数相乘 只是考验能否使用大数相乘 大整数乘法可以模拟乘法运算写 也可以使用分治写法 分治可以优化XY=AC2^N [(A-B)(D-C)+AC ...

  2. python实现循环赛日程表问题的算法_循环赛日程表的分治算法实现实验报告gxl.doc...

    循环赛日程表的分治算法实现实验报告gxl PAGE PAGE 2 深 圳 大 学 实 验 报 告 课程名称: 算法设计与分析 实验项目名称: 分治算法 --矩阵相乘的Strassen算法及时间复杂性分 ...

  3. python实现循环赛日程表问题的算法_循环赛日程表的分治算法实现实验报告_gxl.doc...

    循环赛日程表的分治算法实现实验报告_gxl 深 圳 大 学 实 验 报 告 课程名称: 算法设计与分析 实验项目名称: 分治算法 --矩阵相乘的Strassen算法及时间复杂性分析 或--循环赛日程表 ...

  4. 大数相乘(C语言,分治算法)

    问题: 由于编程语言提供的基本数值数据类型表示的数值范围有限,不能满足较大规模的高精度数值计算,因此需要利用其他方法实现高精度数值的计算,于是产生了大数运算.大数运算主要有加.减.乘三种方法. 下面就 ...

  5. 斐波那契数列取模(大数)分治算法

    斐波那契数列取模(大数)分治算法 这是算法课程上完分之策略后老师留的一道题目: 菲波那契数列如下:1,1,2,3,5,8,13,21,34......其中a[1] = 1, a[2] = 1, a[n ...

  6. 分治算法解大整数相乘问题

    1 问题 有两个n位大整数XXX,YYY,它们数值之分大,如1e10001e10001e1000.现在要计算它们的乘积XYXYXY. 2 分析 2.1 传统方法 逐位相乘.错位相加,时间复杂度O(n2 ...

  7. c语言中大数相乘的方法,C++实现大数相乘算法

    本文实例为大家分享了C++实现大数相乘的具体代码,供大家参考,具体内容如下 首先说一下乘法计算的算法:同样是模拟人工计算时的方法. 从低位向高位乘,在竖式计算中,我们是将乘数第一位与被乘数的每一位相乘 ...

  8. php大数相乘,简单的大数相乘算法

    大数相乘最直接的算法就是模拟小学学到的竖式乘法,可以使用数组或者字符串来存储乘数和被乘数,php代码实现如下: /** * 大数相乘代码 */ function multiply($str1,$str ...

  9. 算法题-大数相乘问题

    今天在网上看到一个大数相乘的问题,题目是这样的:输入两个整数,要求输出这两个数的乘积.输入的数字可能超过计算机内整形数据的存储范围. 分析: 由于数字无法用一个整形变量存储,很自然的想到用字符串来表示 ...

最新文章

  1. AI一分钟 | 小米MIX 2S将于3月27号发布,搭载骁龙845;张朝阳:在研究区块链 但相信AI的力量
  2. 计算机设备布局图,针对不同设备类型创建仪表板布局
  3. 居家学习的核心操作准则:45分钟的专注
  4. JLink接口的SWD接法
  5. ZOJ 3430 Detect the Virus 【AC自动机+解码】
  6. ASP.NET Core 集成测试
  7. 微信小程序request请求封装;微信小程序封装request请求;uni-app小程序封装request请求;
  8. 蚂蚁金服SOFA开源负责人鲁直:不只是中间件,未来会开源更多
  9. Basic Theory of Physically-Based Rendering
  10. 大数据与Hadoop的区别
  11. 快速学会require的使用
  12. Eclipse修改svn地址
  13. java jsonp网络爬虫_JSOUP 爬虫
  14. js——行间样式与非行间样式
  15. 深入探究802.11ac技术
  16. 帝国cms会员中心1.2
  17. [原创]酒好喝,好喝酒,喝好酒,酒喝好
  18. Facebook将对视频进行人物识别及身份标注
  19. 【VUE】【高德地图】如何隐藏(去除)高德地图api左下角logo
  20. mybatis源码学习------Invoker接口及其子类

热门文章

  1. 服务器数据库异常MySQL_服务器 mysql数据库异常
  2. win10固定本机IP地址方案总结
  3. 学计算机专业异构超算,中国科学技术大学超级计算中心
  4. Aidlux边缘设备简介
  5. Django dWebScoket 实时消息推送
  6. 字节跳动音乐梅开二度,腾讯音乐、网易云要警惕了
  7. Go语言学习、结构体
  8. 对今天知识的回顾15
  9. 还在为不会做PPT而担忧嘛,有这个PPT神器,从此秒变王者!
  10. Opencv学习记录(三) —— 得到图像中目标物坐标的简单处理算法(望指正与补充)