分治思想—递归实现大数乘法ACM(含奇数长度处理)
来源:互联网 发布:淘宝网的特点 编辑:程序博客网 时间:2024/06/05 22:57
一般的算法都是O(n^2)这里不再给出。
但是如果使用递归的话复杂度会变为O(n^log3),主要的做法是减少运算次数
对于任意两个数字X,Y
可以将其在中间部分 分解为两部分例如:
1234 -> 12 和 34
5678 -> 56 和 78
(细心的人可能发现就是1234 = 12*10^2 + 34)那么对于任意一个数都可以分解为前后两部分。
我们还是以1234这样的四位数字为例,设1234分解A、B,5678分解为C、D按照一般思路对于乘法有 (以下为竖式)
同时对于形如1234结果可以写为:A*C*10^4+(AD+BC)*10^2+BD
观察那个竖式和这里的式子是不是有一定的规律?
那么1234可以拆为AB(每个字母两位)同样对于12 和34可以拆为A、B(每个字母一位)这样就可以进行递归了。
可以发现这样的复杂度为O(n方)。
下面通过一个小技巧进行化简:首先有:
XY
=(A∗10^(n^2)+B)(C∗10^(n^2)+D)
=AC∗10^n+(AD+BC)∗10(n^2)+BD——————————–(2)
=AC∗10^n+((A+B)(D+C)-AC-BD)∗10^(n^2)+BD —————-(3)
注意第2行到第3行的变化:(AD+BC)∗10(n^2)=((A+B)(D+C)-AC-BD)∗10^(n^2)
其中中间最大括号里面的AC BD 在外面算过,此时加上 (A−B)(D−C)一共只需要三次。而之前每层递归需要四次。
改进后又有:
T(n) =
{O(1),3T(n2)+O(n),n =1 n>1
下面给出模版
#include <iostream>#include <cmath>#include <algorithm>using namespace std;long long multi(long long p , long long q, int len) { if (p == 0 || q == 0)return 0 ; if (len == 1)return p * q; else { long long danwei = pow (10, len); long long danwei2 = pow (10, len / 2); long long a1 = p / danwei2; long long a2 = p % danwei2; long long b1 = q / danwei2; long long b2 = q % danwei2; // printf("1: %lld\n", a1 ); // printf("2: %lld\n", a2 ); // printf("3: %lld\n", b1 ); // printf("4: %lld\n", b2 ); long long temp1 = multi(a1, b1, len / 2); long long temp3 = multi(a2, b2, len / 2); long long temp2 = multi(a1+a2, b1+b2, len / 2) - temp3 - temp1; return (temp1 * danwei + temp2 * danwei2 + temp3); }}int main(int argc, char const *argv[]){ long long a , b; scanf("%lld", &a); scanf("%lld", &b); // printf("->%lld\n", a); // printf("->%lld\n", b); int index = 0,index2=0; int c = a ; while (c) { c /= 10; index ++; } c = b ; while (c) { c /= 10; index2 ++; } cout << multi(a, b, max(index2,index)); return 0;}
大家可能发现这样的写法对于奇数没法处理:
下面只要讨论奇数情况就可以:
附上完整代码:
#include <iostream>#include <cmath>#include <algorithm>using namespace std;long long multi(long long p , long long q, int len) { if (p == 0 || q == 0)return 0 ; if (len == 1)return p * q; long long danwei = pow (10, len); long long danwei2 = pow (10, len >> 1 );//这个是除以2 long long a1 = p / danwei2; long long a2 = p % danwei2; long long b1 = q / danwei2; long long b2 = q % danwei2; if ((len & 1) == 1) //尝试一下位运算,如果为奇数 123 123这类 { // printf("1: %lld\n", a1 ); // printf("2: %lld\n", a2 ); // printf("3: %lld\n", b1 ); // printf("4: %lld\n", b2 ); long long temp1 = multi(a1, b1, (len >> 1) + 1); long long temp3 = multi(a2, b2, (len >> 1)); long long temp2 = multi(a1 + a2, b1 + b2, (len >> 1) + 1) - temp3 - temp1; danwei = pow (10, len - 1); return (temp1 * (danwei) + temp2 * danwei2 + temp3); } else { long long temp1 = multi(a1, b1, len >> 1); long long temp3 = multi(a2, b2, len >> 1); long long temp2 = multi(a1 + a2, b1 + b2, len >> 1) - temp3 - temp1; return (temp1 * danwei + temp2 * danwei2 + temp3); } return 0;}int main(int argc, char const *argv[]){ long long a , b; scanf("%lld", &a); scanf("%lld", &b); // printf("->%lld\n", a); // printf("->%lld\n", b); int index = 0, index2 = 0; int c = a ; while (c) { c /= 10; index ++; } c = b ; while (c) { c /= 10; index2 ++; } if (index != index2) cout << "您输入的长度不相等" << endl; else cout << multi(a, b, max(index2, index)); return 0;}
- 分治思想—递归实现大数乘法ACM(含奇数长度处理)
- 大数乘法的分治策略C++实现
- 大数乘法 分治法
- 分治法 大数乘法
- 分治法求大数乘法
- 递归分治-大整数乘法
- 7、JAVA实现快排--分治+递归的思想
- Java使用分治递归的思想实现快速排序
- 求二维平面最近点对算法; 分治思想; 递归写的好精准,模仿ACM模板写的.;很多细节处理的很漂亮;
- 大数乘法、大数加法实现
- 采用分治法进行大数乘法运算
- 九、递归和分治思想
- 大数乘法——数组实现
- 大数乘法——C++实现
- 大数乘法的实现
- 大数乘法实现代码
- 大数乘法C++实现
- 大数乘法的实现
- 如何处理 JavaScript 内存泄露
- Word2013制作中国的传统福字在屋门上贴的福字(福倒了)
- Sublime安装与常用配置
- 直播App中Android酷炫礼物动画实现方案(上篇)
- php $_REQUEST 数据错误
- 分治思想—递归实现大数乘法ACM(含奇数长度处理)
- SpringCloud Zuul过滤器返回值拦截
- Java 集合深入理解(11):LinkedList
- 子页面调用父页面对象修改父页面span(div或者input)值
- iOS 11开发教程(六)iOS11Main.storyboard文件编辑界面
- 从svn中,检出下来的项目,在是tomcat服务器中服中无法加载!()
- make: *** [sapi/cli/php] Error 1
- OkHttp,一个专注于性能和易用性的 HTTP 客户端
- 项目组合管理、项目集管理、项目管理和组织级项目管理之间的关系