Karatsuba乘法

        Karatsuba算法是将普通乘法的时间复杂度从O(n^2)时间降低到O(nlog3)的一种乘法算法。是一种计算大数乘法的优秀算法。

Karatsuba算法主要应用于两个大数的相乘,原理是将大数分成两段后变成较小的数位,然后做3次乘法,并附带少量的加法操作和移位操作。

现有两个大数,x,y。

首先将x,y分别拆开成为两部分,可得x1,x0,y1,y0。他们的关系如下:

x = x1 * 10m + x0;

y = y1 * 10m + y0。其中m为正整数,m < n,且x0,y0 小于 10m。

那么 xy = (x1 * 10m + x0)(y1 * 10m + y0)

=z2 * 102m + z1 * 10m + z0,其中:

z2 = x1 * y1;

z1 = x1 * y0 + x0 * y1;

z0 = x0 * y0。

此步骤共需4次乘法,但是由Karatsuba改进以后仅需要3次乘法。因为:

z1 = x1 * y0+ x0 * y1

z1 = (x1 + x0) * (y1 + y0) - x1 * y1 - x0 * y0,

故z1 便可以由一次乘法及加减法得到。

实例展示

设x = 12345,y=6789,令m=3。那么有:

12345 = 12 * 1000 + 345;

6789 = 6 * 1000 + 789。

下面计算:

z2 = 12 * 6 = 72;

z0 = 345 * 789 = 272205;

z1 = (12 + 345) * (6 + 789) - z2 - z0 = 11538。

然后我们按照移位公式(xy = z2 * 10^(2m) + z1 * 10^(m) + z0)可得:

xy = 72 * 10002 + 11538 * 1000 + 272205 = 83810205。

#include<iostream>
#include<cmath>
#include<stdio.h> 
using namespace std;

//找到x的位数  
long maxlen(long x, long y)
{
	int iMax = 0;
	int iTmp = 1;
	while (x /= 10)
		iTmp++;
	iMax = iTmp;
	iTmp = 1;
	while (y /= 10)
		iTmp++;
	return iMax > iTmp ? iMax : iTmp;
}
long Karatsuba(long x, long y)
{
	if (x<10 || y<10) return x*y;
	else {
		long m, x1, x0, y1, y0, z0, z1, z2;
		m = maxlen(x, y) / 2;
		x1 = x / (int)pow(10, m);
		x0 = x - x1*(int)pow(10, m);
		y1 = y / (int)pow(10, m);
		y0 = y - y1*(int)pow(10, m);
		z2 = Karatsuba(x1, y1);
		z0 = Karatsuba(x0, y0);
		z1 = Karatsuba((x1 + x0), (y1 + y0)) - z2 - z0;
		return z2*(int)pow(10, 2 * m) + z1*(int)pow(10, m) + z0;
	}
}
int main()
{
	long a, b;
	cin >> a >> b;
	cout << Karatsuba(a, b) << endl;
	//cout << a*b << endl;
	return 0;
}

        还有一篇写的很好的博文:点这里

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值