您的位置:首页 > 其它

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

2014-07-15 19:46 162 查看
在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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数论 素数