Miller-Rabin素数检测
费马小定理:没人不会吧。
二次探测:如果(n)是质数,(x^2 equiv 1 (mod n))的解只有(x equiv 1)或(x equiv n-1 (mod n))。
实现方法:
选取一些质数。(n)不超过(3 imes 10^{18})的时候只需要(2 sim 23),(n)在unsigned long long
范围内时只需要(2 sim 37)。对于每个质数:
-
使用费马小定理的逆否定理检测。
-
此时,我们有(p^{n-1} equiv 1 (mod n)),如果不出意外(n)是质数的话,根据二次探测定理,(p^{frac{n-1}{2}},p^{frac{n-1}{4}}...)在模意义下都应该为(1),直到一次取到(n-1)时规律消失。
所以我们可以倒序处理,根据第一次出现(n-1)的位置进行探测。
代码
int mi[9]={2,3,5,7,11,13,17,19,23};
inline LL qmul(LL x,LL y,LL mod){
LL z=(long double)x/mod*y+0.5;
return ((x*y-z*mod)%mod+mod)%mod;
}
inline LL qpow(LL x,LL y,LL mod){
LL ret=1,tt=x%mod;
while(y){
if(y&1)ret=qmul(ret,tt,mod);
tt=qmul(tt,tt,mod);
y>>=1;
}
return ret;
}
inline bool miller_rabin(LL x){
if(x==1)return false;
rin(i,0,8)if(x==mi[i])return true;
rin(i,0,8)if(x%mi[i]==0)return false;
LL a=x-1;int b=0;
while(!(a&1))a>>=1,++b;
rin(i,0,8){
if(qpow(mi[i],x-1,x)!=1)return false;
LL now=qpow(mi[i],a,x);
if(now==1||now==x-1)continue;
rin(j,1,b-1){
now=qmul(now,now,x);
if(now==x-1)break;
if(j==b-1)return false;
}
}
return true;
}
低于线性复杂度的积性函数的前缀和处理方法
看这篇:杜教筛&min_25筛复习