64位整数乘法

本文探讨了在算法竞赛中处理大数乘法模运算的两种高效方法,避免了直接相乘引起的溢出和累加操作导致的时间复杂度过高问题。通过二进制表示和利用除法取余特性,提供了既快速又准确的解决方案。

//总结自李煜东著《算法竞赛进阶指南》

问题:求a乘b对p取模的值,其中1<=a,b,p<=10^18。

简单的暴力相乘显然会溢出(相当于对64位整数最大值+1取模),对a进行b次累加显然会超时。

法一:

仿照快速幂,用二进制表示b。

 1 typedef long long ll;
 2 
 3 inline ll mul(ll a, ll b, ll p) {
 4     a %= p, b %= p;
 5     ll ans = 0;
 6     while (b) {
 7         if (b & 1) ans = (ans + a) % p;
 8         a = a * 2 % p, b >>= 1;
 9     }
10     return ans;
11 }

法二:

利用a*b%p=a*b-floor(a*b/p)*p求解,其中floor函数表示向下取整。

 1 typedef long long ll;
 2 
 3 inline ll mul(ll a, ll b, ll p) {
 4     a %= p, b %= p;
 5     ll c = (long double)a * b / p;
 6     ll ans = a * b - c * p;
 7     if (ans < 0) ans += p;
 8     else if (ans >= p) ans -= p;
 9     return ans;
10 }

值得一提的是,尽管a*b和c*p可能溢出,但这并不影响,因为a*b-c*p一般不会超过p-1,我们只关心他们的低位。

转载于:https://www.cnblogs.com/Mr94Kevin/p/10325252.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值