【小技巧】O(1)快速乘

本文深入探讨了在处理大数模运算时的优化方法,特别是在CRT算法中的应用。介绍了如何通过二进制拆分将乘法转化为加法,实现O(logn)的快速乘法。同时,提供了一种利用longdouble进行O(1)快速乘法的方法,有效避免了在处理大数时的时间和精度问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 问题:求 a×b mod pa\times b\ mod\ pa×b mod pa,b,pa,b,pa,b,plong long 范围内。
  • CRT 等算法中应用广泛。
  • 为了处理模数在 int 范围外的情况,就是两数相乘可能会爆 long long 时,我们不能直接用整型的乘法来计算。
  • 首先我们可以进行二进制拆分,化乘法为加法,类似快速幂那样,写出一个 O(log⁡n)O(\log n)O(logn) 的快速乘
typedef long long s64; 

inline void add(s64 &a, const s64 &b)
{
	a += b; 
	if (a >= mod)
		a -= mod; 
}

inline s64 qmul(s64 a, s64 b, const s64 &mod)
{
	a = (a % mod + mod) % mod; 
	b = (b % mod + mod) % mod; //这两行依据情况不写
	s64 res = 0; 
	for (; b; b >>= 1, add(a, a, mod))
		if (b & 1)
			add(res, a, mod); 
	return res; 
}
  • 多次使用时,为了避免毒瘤出题人卡时间(或是为了优化常数),我们可以利用 long double 写出一个优秀的 O(1)O(1)O(1) 快速乘。
  • 简单原理:a×b mod p=a×b−⌊a×bp⌋×pa\times b\ mod\ p=a\times b-\lfloor \frac{a\times b}{p}\rfloor\times pa×b mod p=a×bpa×b×p
  • 利用 long double 来处理这个 ⌊a×bp⌋\lfloor \frac{a\times b}{p}\rfloorpa×b
  • 然后处理一下浮点误差就可以了。
  • 模数较大时可能会出锅。
  • 不过出锅概率很小
typedef long long s64; 
typedef long double ld; 

inline s64 qmul(s64 a, s64 b, s64 mod)
{
	a = (a % mod + mod) % mod; 
	b = (b % mod + mod) % mod; //这两行依据情况不写
	s64 res = a * b - (s64)((ld)a / mod * b + 1e-8) * mod; 
	return res < 0 ? res + mod : res;  
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值