快速乘详解

两个long long 的数相乘,模一个long long的数,怎么处理?

直接乘是肯定不行的,于是我们就要用到快速乘。

1.用long double

首先,我们知道a%b=a−⌊ab⌋×ba\%b=a-\lfloor\frac{a}{b}\rfloor\times ba%b=aba×b,所以x×y%p=x×y−⌊x×yp⌋×px\times y\%p=x\times y-\lfloor\frac{x\times y}{p}\rfloor\times px×y%p=x×ypx×y×p

这里x,y,px,y,px,y,p都是long long的,显然x×yx\times yx×y可能会溢出,但是减去⌊x×yp⌋×p\lfloor\frac{x\times y}{p}\rfloor\times ppx×y×p之后的结果肯定是小于ppp的。溢出后减回来结果是一样的。时间复杂度为O(1)O(1)O(1),适合用于卡常数的题目。

但是,因为long double有精度问题,所以如果数组过大的话返回值就会出问题。

code

long long ch(long long x,long long y,long long p){
	return (x*y-(long long)((long double)x/p*y)*p+p)%p;
}

2.用二进制

与快速幂原理相似,原本x×yx\times yx×yx+x+x+⋯+xx+x+x+\dots+xx+x+x++x连续加yyyxxx。我们可以优化一下,对于yyy转为二进制中的第iii位,如果这一位为1,则ans+=x×2ians+=x\times 2^ians+=x×2i。所以只需枚举iii,具体与快速幂相似,时间复杂度为O(y)O(y)O(y)

code

long long ch(long long x,long long y,long long p){
	long long re=0;
	for(;y;y>>=1,x=(x+x)%p){
		if(y&1) re=(re+x)%p;
	}
	return re;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值