分治算法实现两个n位的正整数相乘

分治算法实现两个n位的正整数相乘

分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立与原问题性质相同,最后按原问题的要求,将子问题的解逐层合并构成原问题的解,快速排序算法便是基于分治策略的一种排序方法。

这里要讲的是利用分治算法来实现两个n位的正整数相乘:


具体思路

  1. 给定两个均为n位的十进制正整数x、y,将其拆分为左右各一半的xl、xr、yl、yr。具体表示如下: x = xl*10^(n/2) + xr, y = yl*10^(n/2) + yr。例如12345=123*10^(5/2)+45。
  2. x*y=[xl*10^(n/2) + xr]*[yl*10^(n/2) + yr]=xl*yl*10^n+(xr*yl+xl*yr)*10^(n/2)+xr*yr
    所以x*y的问题就转化为4个规模较小的子问题,这些子问题相互独立且性质相同,符合分治策略,但转化后的时间复杂度为T(n) = 4 * T(n / 2) + θ(n)
    通过master定理可以求得 T(n) = θ(n ^ 2),并未有丝毫优化!
    但伟大的数学家高斯发现xr*yl+xl*yr=(xl+xr)(yl+yr)-xl*yl-xr*yr,这样就可以将x*y**分解成关于3个乘积的子问题*,即x*y=[xl*10^(n/2) + xr] * [yl*10^(n/2) + yr] = xl*yl*10^n + [(xl+xr) * (yl+yr) - xl*yl - xr*yr] * 10^(n/2) + xr*yr。这样时间复杂度T(n) = 3 * T(n / 2) + θ(n),通过master定理求得,T(n) = O(n^log2(3) ) = O(n^1.59 )

伪代码实现

function DC_Multiply(x,y,n)
Input: positive integers x and y and the bits of them
Otput: Their product

if n = 1: return x*y

xl, xr = leftmost [n/2], rightmost [n/2] bits of x
yl, yr = leftmost [n/2], rightmost [n/2] bits of y

pro1 = DC_Multiply(xl, yl, (n+1)/2)
pro2 = DC_Multiply(xr, yr, n/2)
pro3 = DC_Multiply(xl+xr, yl+yr)
return p1*10^[2*(n/2)]+(p3-p1-p2)*10^(n/2)+p2

完整C++代码实现

#include <iostream>
#include <cmath>
#include <cstdlib>
// 分治算法实现两个n位的正整数相乘

using namespace std;
// 简单起见,x和y均为n位的正整数,n为奇偶均可
int DC_Multiply(int x, int y, int n) {
    int xl, xr, yl, yr;
    int pro1, pro2, pro3;
    if (n == 1) {
        return x*y;
    } else {
        int temp = pow(10, n/2); 
        xl = x / temp;
        xr = x % temp;
        yl = y / temp;
        yr = y % temp;
        pro1 = DC_Multiply(xl, yl, (n+1)/2);
        pro2 = DC_Multiply(xr, yr, n/2);
        pro3 = DC_Multiply(xl+xr, yl+yr, (n+1)/2);
        return (pro1 * pow(10, 2*floor(n/2)) + (pro3-pro1-pro2) * pow(10, n/2) + pro2);   //pro1对应相乘的10的幂次要注意
    }
}
int main() {
    string sx, sy;
    int x, y;

    cout << "分治算法实现两个相同位数的正整数相乘:" << endl;
    cout << "请输入正整数x:";
    cin >> sx;
    cout << "请输入正整数y:";
    cin >> sy;

    int length = sx.length();
    // string转int类型函数
    x = atoi(sx.c_str());
    y = atoi(sy.c_str());

    cout << x << "*" << y << "==" << DC_Multiply(x, y, length) << endl;
    return 0; 
}

运行结果截图:
这里写图片描述

反思与总结

首选是对分治策略更进一步的理解,再者就是优化就在身边,即使是两个数相乘也一样能找到更为优化的解法,不过美中不足的是必须确保两个数均为n位数,除此之外,对string转int类型又有了一定的温习,这样就不至于再傻乎乎的要求用户输入数字的位数。

  • 4
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值