LOJ143(Miller Rabin素数测试)

LOJ143

题意:1e5个(1e18)的数,分别判断它们是不是质素。

题解:Miller Rabin素数测试(费马小定理,二次探测)

  • 当被测试数在某一个范围内时,我们可以通过选取适当的测试底数让 MillerRabin 素数测试对于这个范围内的每一个数都能够正确地得出结果。下面是节选自 维基百科 的选取 a的方式。
  • 当 N<4,759,123,141选取 a=2,7,61即可确保算法得出正确结果。
  • 当 N<3,825,123,056,546,413,051≈3∗10^18选取 a=2,3,5,7,11,13,17,19,23即可确保算法得出正确结果。
  • 当 N<18,446,744,073,709,551,616=2^64选取 a=2,3,5,7,11,13,17,19,23,29,31,37即可确保算法得出正确结果

#include
#define ll long long 
#define i128 __int128
using namespace std;
ll n;
int primes[19]={2,3,5,7,11,13,17,19,23,29,31,37};
ll poww(ll a,ll b,ll c){
    ll ans=1;i128 base=a;
    while(b){
        if(b&1)ans=ans*base%c;
        base=base*base%c;
        b>>=1;
    }
    return ans;
}
bool miller_rabin(ll n){
    for(int i=0;i<=8;i++){
        if(primes[i]==n)return 1;
        else if(primes[i]>n)return 0;
        ll t=poww(primes[i],n-1,n),x=n-1;
        if(t!=1)return 0;
        while(t==1&&x%2==0){
            x/=2;
            t=poww(primes[i],x,n);
            if(t!=1&&t!=n-1)return 0;
        }
    }
    return 1;
}
int main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    while(cin>>n){
         if(miller_rabin(n))puts("Y");else puts("N");
    }
    return 0;
}

 

你可能感兴趣的:(数论,Miller,Rabin素数测试)