慢速乘
- 这种方法常常用在快速幂里面,替换整数乘法的部分,因为两个大整数相乘可能直接爆掉long longlong\ longlong long,原理如下
- 因为一个数总是有唯一的二进制表示,所以我们把指数表示成二进制,比如a×3a\times3a×3,那么因为3=(11)23=(11)_23=(11)2,所以a×3=a×2+a×1a\times3=a\times2+a\times1a×3=a×2+a×1,所以可以很自然的写出程序
typedef long long ll;
ll slowmul(ll x, ll y, ll mod){
ll ans = 0;
while(y){
if(y & 1){
ans = (ans + x);
if(ans > mod) ans %= mod;
}
x = 2 * x % mod;
y >>= 1;
}
return ans;
}
- 时间复杂度是O(log(y))O(log(y))O(log(y)),因为通常情况下yyy都极大,而且需要进行多次乘法,所以速度相对比较慢,不过这种方法基本不会出现溢出问题,因为把一个数一个一个的加再取模已经是优化到极限了,如果还会溢出,那就只能用高精度算法
快速乘
xy%p=xy−⌊x×yp⌋×pxy\%p=xy-\lfloor \frac{x\times y}{p}\rfloor\times pxy%p=xy−⌊px×y⌋×p
- 根据取模的性质有上述等式成立,然后就可以用一种神奇的溢出方式解决这个问题,但是好像数字过大时候可能会有误差,慎用此法
- 记一下,参考2009年成都七中骆可强国家集训队论文——论程序底层优化的一些方法与技巧
typedef long double ld;
ll ksc(ll x,ll y,ll p){
ll z=(ld)x/p*y;
ll res=(ull)x*y-(ull)z*p;
return (res+p)%p;
}
这篇博客介绍了两种大整数乘法的算法:慢速乘和快速乘。慢速乘通过二进制分解指数实现,避免了长整数直接相乘可能的溢出问题,时间复杂度为O(log(y))。快速乘则利用取模性质减少溢出,但可能在大数字下存在误差。文章还提到了2009年骆可强的优化技巧论文作为参考。
5398

被折叠的 条评论
为什么被折叠?



