【数论】【素数】素数相关基础——基础操作

在long long范围内,我们经常进行+、-、*、/、%、^运算,其中+、-、/不会有什么问题。

对于乘法和幂运算,我们需要考虑爆掉longlong的情况,而题目也一般会要求你模除一个数,也即a*b%c,a^b%c,但是显然a*b,a^b也一样会爆longlong,因此乘法和幂运算不能直接算,需要一些特殊的方法。

 

1、 乘法取模运算

实现方法是将一个乘数二进制拆分,另外一个乘数进行多次乘法并取模。


LL mul_mod(LL a,LL b,LL c){
    a%=c;
    b%=c;
    long long ret=0;
    while(b)
    {
        if(b&1){ret+=a;ret%=c;}
        a<<=1;
        if(a>=c)a%=c;
        b>>=1;
    }
    return ret;
}



 
 

2、 幂取模运算

实现方法是将指数进行二进制拆分,运用快速幂求解,中间的乘法用上面的mul_mod运算

LL pow_mod(LL a,LL tmp,LL n){
    LL p[32],i=0;
    while (tmp>0){
        p[i++]=tmp & 1 ? 1 : 0;
        tmp=tmp>>1;
    }

    LL s=1;
    for (i--;i>=0;i--){
        s=s*s%n;
        if (p[i]==1) s=mul_mod(s,a,n);
    }

    return s;
}



 
3、最大公约数与最小公倍数 

最小公约数的经典求法是欧几里德算法(也即辗转相除法),最小公倍数即为两数乘积除以最大公约数。

需要说明的负数也是有约数的,并且约数的相反数也是一个约数。

假设a<0,则|a|的约数也同样是a的约数,同样的|a|的任意约数也是a的约数。

不失一般性,我们通常直接认为约数为正数。

LL gcd(LL a,LL b){

    LL c;
    if (a==0) return 1;
    if (a<0) return gcd(-a,b);
    if (b<0) return gcd(a,-b);

    if (a<b){
        LL x=a;
        a=b;
        b=x;
    }

    c=b;
    while (b!=0){
        c=a%b;
        a=b;
        b=c;
    }
    return a;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值