ACM-较大的数乘法取模技巧*

比如模数是1e15这种,相乘的时候爆LL了,但是又不想用大数,咋办呢?

 

long long ksc(long long a, long long b, long long mod){
    long long res = 0;
    while(b){
        if(b&1) res = (res + a)%mod;
        (a<<=1)%=mod;
        b >>= 1;
    }
    return res;
}

 

 

转long double再搞回来

《算法竞赛进阶指南》 
听说很稳? 
abmodp=ababppa∗bmodp=a∗b−⌊a∗bp⌋∗p 
用long double来计算abp⌊a∗bp⌋,误差很小,因为long double的特性是存不下就舍弃低位,再把它转成long long。直接用long long来计算。long long爆掉了会让符号位出错,但是小于2^63的位是不会挂的,这正好符合我们的需求。

 

LL mul(LL a,LL b,LL p){
    LL tmp=(a*b-(LL)((long double)a/p*b+1e-8)*p);
    return tmp<0?tmp+p:(tmp>=mo?tmp-mo:tmp);
}
LL mul(LL x, LL y) {
    ll z = (ld) x * y / mo; z = x * y - z * mo;
    if(z < 0) z += mo; else if(z > mo) z -= mo;
    return z;
}

 

ll mul(ll a,ll b,ll p){
    ll tmp=(a*b-(ll)((long double)a/p*b+1e-8)*p);
    return tmp<0?tmp+p:(tmp>=mo?tmp-mo:tmp);
}

 

posted @ 2018-09-10 14:22  shuai_hui  阅读(1100)  评论(0编辑  收藏  举报