算法进阶——64位整数乘法

文章介绍了两种计算大整数a乘以b对给定模数p取模的方法。方法一是基于快速幂思想,将b转化为二进制表示,然后通过递推计算每个乘积项。方法二是利用模算术性质,将乘法转换为减法和除法操作,通过浮点数计算近似值并调整范围。这两种方法都适用于处理大整数运算,且在64位整数范围内有效。
摘要由CSDN通过智能技术生成

移位运算例题

求 a 乘 b 对 p 取模的值,其中 1 ≤ a , b , p ≤ 1 0 18 求a乘b对p取模的值,其中1 \le a,b,p \le 10^{18} abp取模的值,其中1a,b,p1018

方法一

类似于快速幂的思想,把整数b用二进制表示,即
b = c k − 1 ∗ 2 k − 1 + c k − 2 ∗ 2 k − 2 + ⋯ + c 0 ∗ 2 0 b=c_{k-1}*2^{k-1}+c_{k-2}*2^{k-2}+ \cdots + c_0*2^0 b=ck12k1+ck22k2++c020
那么
a ∗ b = c k − 1 ∗ a ∗ 2 k − 1 + c k − 2 ∗ a ∗ 2 k − 2 + ⋯ + c 0 ∗ a ∗ 2 0 a*b=c_{k-1}*a*2^{k-1}+c_{k-2}*a*2^{k-2}+ \cdots + c_0*a*2^0 ab=ck1a2k1+ck2a2k2++c0a20
因为
a ∗ 2 i = ( a ∗ 2 i − 1 ) ∗ 2 a*2^i=(a*2^{i-1})*2 a2i=(a2i1)2

若已求出 a ∗ 2 i − 1 m o d    p a*2^{i-1}\mod p a2i1modp ,则计算 $ (a*2^{i-1})*2 \mod p$ 时 ,运算过程中的每一步都不超过 2 ∗ 1 0 1 8 2*10^18 21018,在64位整数 longlong的表示范围内,很容易通过k次递推求出每个乘机项。当 c i = 1 c_i=1 ci=1时,把该成绩项累加到答案中即可,时间复杂度为 O ( l o g 2 b ) O(log_2b) O(log2b)

代码

long long mul(long long a, long long b, long long p)
{
	long long ans = 0;
	for(;b;b>>=1)
	{
    	if(b&1)
      		ans = (ans+1)%p;
    	a = a*2%p;
  	}
  	return ans;
}

方法二

利用 a ∗ b m o d    p = a ∗ b − [ a ∗ b / p ] ∗ p a*b\mod p = a*b-[a*b/p]*p abmodp=ab[ab/p]p,其中[ ]表示下取整

首先,当 a , b < p a,b<p a,b<p时, a ∗ b / p a*b/p ab/p下取整后也一定小于p。我们可以利用浮点数执行 a ∗ b / p a*b/p ab/p的运算,而不用关心小数点之后的部分。浮点类型 long double 在十进制下有效数字有18 到19位,足够胜任。当浮点数精度不足以保存精确数值时,它会像科学计数法一样舍弃低位,正好符合需求

另外虽然 a ∗ b a*b ab [ a ∗ b / p ] ∗ p [a*b/p]*p [ab/p]p的可能很大,但是二者的差一定在0到 p − 1 p-1 p1之间,我们只关心他们较低的几位即可。因此,我们可以用 long long 来保存 a ∗ b a*b ab [ a ∗ b / p ] ∗ p [a*b/p]*p [ab/p]p各自的结果。整数运算一处相当于舍弃高位,也符合需求

代码

	long long mul(long long a, long long b, long long p)
	{
		a %= p , b%=p;//当a,b一定在0~p之间时,此行不必要
		long long c = (long double)a*b/p;
		long long ans = a*b-c*p;
		if(ans<0)
			ans += p;
		else if(ans>=p)
			ans -= p;
		return ans;
	}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

栖林_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值