inline ll Mul(ll a,ll b,ll mod)
{
ll ret=a*b-(ll)((long double)a*b/mod+0.5)*mod;
return ret<0?ret+mod:ret;
}
以上代码可以在O(1)的时间内完成两数乘法的取模,其中模数达到了long long级别,且这种方法能够求出正确的结果。
最近复习数论,用到了这个小技巧。我想知道他的原理,于是上网百度了一下,发现这出自一个国集论文。
以下是原文:
为了下面叙述方便,记
A=a*b;
B=(ll)((long double)a*b/mod+0.5)*mod;
现在我已经理解到,对于A,B关于long long 溢出的部分之间的差只可能是0或1。那么根据论文的意思,可以如下分类:
我对差为1这个分类有些困惑。下面我将举一个例子描述我的困惑:
假设有一个数据类型,他只能存储0到9。
我们用这个快速乘的原理计算3×4%7的值。
先算3×4。由于他爆了这个数据类型,所以结果是2。
再算 ⌊73×4⌋×7。 按照快速乘,由于计算这个值得时候用到了long double ,所以会算出精确值7。
根据这行代码:
return ret<0?ret+mod:ret;
会算出答案2−7+mod=2−7+7=2
可事实上3×4%7=5。
请问我的理解哪里有问题?
另外,我对long double那一块的原理已经清楚了,不需要再解释了。
请不要有无意义回复,谢谢