慢速乘和快速乘简单回顾和整理

慢速乘

  • 这种方法常常用在快速幂里面,替换整数乘法的部分,因为两个大整数相乘可能直接爆掉 l o n g   l o n g long\ long long long,原理如下
  • 因为一个数总是有唯一的二进制表示,所以我们把指数表示成二进制,比如 a × 3 a\times3 a×3,那么因为 3 = ( 11 ) 2 3=(11)_2 3=(11)2,所以 a × 3 = a × 2 + a × 1 a\times3=a\times2+a\times1 a×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 ( l o g ( y ) ) O(log(y)) O(log(y)),因为通常情况下 y y y都极大,而且需要进行多次乘法,所以速度相对比较慢,不过这种方法基本不会出现溢出问题,因为把一个数一个一个的加再取模已经是优化到极限了,如果还会溢出,那就只能用高精度算法

快速乘

x y % p = x y − ⌊ x × y p ⌋ × p xy\%p=xy-\lfloor \frac{x\times y}{p}\rfloor\times p xy%p=xypx×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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Clarence Liu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值