关于长整形乘法取模的溢出问题的解决办法&O(1)快速乘

//依旧是搬运..

 

最近看到一个快速乘法的板子,心生好奇,仔细看了看,跟快速幂的写法很像,然而却不是“快速”乘法,但却能解决乘法取模的溢出问题。

众所周知,C++中,对两个长整形进行乘法并取模,在乘法时得到的中间值有可能会超过long long的范围,从而产生数据溢出,得到不可预知的结果。而在程序设计竞赛中,这种情况是经常会出现的,需要我们掌握处理的办法。那么针对这种问题我们有没有解决办法呢?答案是有的。

首先我们可以先考虑一种做法:按位乘。对于两个十进制的数字a,b,我们可以将b一位一位的与a相乘,并在每次进位时,将a*10并对p取模。当然,取的模与两数乘法取的模一致。这样,每步得到的结果便是b当前位数字与a的值的乘积。每次相乘,将得到的结果相加并进行取模。这样,便可得出a*b%p。

考虑更接近计算机的做法:将两个数视为2进制,此时b的每一位只能是0或1,再次减少了进行乘法的次数,算法的时间复杂度为O(log b)。笔者也不清楚这样处理与直接乘法消耗时间的优劣,但对于处理可能溢出的数据,这样的做法很有效。

贴一下代码:

long long q_mul(long long a,long long b,long long p)
{
    long long sum = 0;
    while(b)
    {
        if(b&1)
            sum = (sum+a)%p;
        a=a<<1;
        a%=p;
        b=b>>1;
    }
    return sum;
}

有任何的问题或指正,欢迎私信。

//2021.5 update

在做ccpc2018final时学到了复杂度为o(1)的快速乘,添加至本文中。

inline long long mul(long long a,long long b,long long c){return (a*b-(long long)((long double)a*b/c)*c+c)%c;}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值