首页 > 其他 > 详细

快速乘

时间:2021-05-30 20:02:36      阅读:22      评论:0      收藏:0      [点我收藏+]

快速乘

在我们进行乘法运算的时候,很多情况下会爆\(long\:long\),所以我们急需寻找一种高效的方法来完成乘法运算并且不会爆\(long\:long\)

一、复杂度为\(o(logN)\)的快速乘

移位快速乘,思想是把\(a\times b\%p\)中的\(b\),对其进行二进制拆分,把\(b\)拆成二进制形式。\(a\times b=C_{k-1}\times a\times2^{k-1}+C_{k-2}\times a\times2^{k-2}+\dots+C_{0}\times a\times2^{0}\),其中\(c\)表示二进制数位。

例如:\(21\times13\),将\(13\)转化成二进制\(1101\),则就是\(20\times2^0+20\times2^2+20\times2^3\)。(类似于快速幂)

typedef long long ll;
ll qmul(ll n, ll b, ll mod){
	ll res = 0;
	while(n){
		if(n & 1) res = (res + b) % mod;
		b = (b + b) % mod;
		n >>= 1;
	}
	return res % mod;
}

二、复杂度为\(O(1)\)的快速乘

利用的是很简单的一个浮点数类型。\(long\:double\)能保证数字的精确程度,然后再把这个数字进行计算。计算的方式很简单,\(a\times b\%p=a\times b-[\frac {a\times b}{p}]\times p\)

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll qmul(ll x, ll y, ll mod){
	ll temp = (ld)x / mod * y;
	ll res = (ull)x * y - (ull)temp * mod;
	return (res + mod) % mod;
}

看到这份代码有没有感到十分奇怪? 它直接用了乘法操作的啊? 这不直接爆了吗?但是它就是可以直接算出正确答案来。因为它很巧妙的运用了自动溢出这个操作,我们的代码中的\(temp\)就表示 \(?\frac{x\times y}{p}?\),所以我们要求的就变成了 \(x\times y??\frac{x\times y}{p}?\times p\) ,虽然这两个部分都是会溢出的,但(\(unsigned\))保证了它们溢出后的差值基本不变,所以即使它会溢出也不会影响最终结果的!

快速乘

原文:https://www.cnblogs.com/hy2001/p/14828282.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!