简单数论(五)------Miller Rabin 素数判定

本来简单数论5准备写高斯消元的但是咕掉了,所以简单数论5改成了素数判定,高斯消元之后直接补到(四)里面

 简单数论(五)------Miller Rabin 素数判定

 PartI 素数判定

如果现在给你一个数N,你要怎样判断他是否是素数,显然我们可以直接枚举1-sqrt(N)的数能否整除N,如果可以一定是合数

但这样的时间复杂度很不优秀

这时就要用到Miller Rabin算法了

 PartII 前置知识---费马小定理和二次探测

(1):费马小定理:若P是质数,且(a,p)=1,ap-1≡1 (mod P)

  (2): 二次探测:对于素数P,能够满足x2≡1 (mod P)的同余类x只有x≡1 (mod P)和x≡p-1 (mod P)

PartIII  算法流程(对于N)

(1):筛掉偶数

(2):找到一个最大的s使得2s*t=N-1

(3):随机选取质数a,我们先算出 a^t,然后不断地平方并且进行二次探测(进行 s 次)。

#include<bits/stdc++.h>

using namespace std;

inline int read()
{
    int f=1,x=0;
    char ch;
    do
    {
        ch=getchar();
        if(ch=='-') f=-1;
    }while(ch<'0'||ch>'9');
    do
    {
        x=(x<<3)+(x<<1)+ch-'0';
        ch=getchar();
    }while(ch>='0'&&ch<='9');
    return f*x;
}

typedef long long ll;

ll n;
ll p[12]={2,3,5,7,11,13,17,19,23,29,31,37};

inline ll Pow(ll a,ll b,ll c)
{
    ll ans=1,mul=a;
    while(b)
    {
        if(b&1)
        {
            ans*=mul;
            ans%=c;    
        }
        mul*=mul;
        mul%=c;
        b>>=1;
    }
    return ans%c;
}

inline bool Miller_Rabin(ll x)
{
    if(x==1){
        return false;
    }
    if(x==2) return true;
    if(x%2==0) return false;
    bool f=1;
    for(ll i=0;i<12;i++)
    {
        if(p[i]==x) return true;
        ll t=x-1,s=0;
        while(t%2==0){
            t/=2;
            s++;
        }
        ll cur=Pow(p[i],t,x);
        if(cur==1) continue;
        for(ll j=1;j<=s;j++)
        {
            ll nxt=cur*cur%x;
            if(nxt==1&&cur!=1&&cur!=x-1)
            {
                f=0;
                break;
            }
            cur=nxt;
            if(cur==1) break;
        }
        if(cur!=1) f=0;
        if(!f) break;
    }
    return f;
    
}

int main()
{
    n=read();
    if(Miller_Rabin(n))
    {
        cout<<"IS PRIME"<<endl;
    } 
    else cout<<"NOT PRIME"<<endl;
}

猜你喜欢

转载自www.cnblogs.com/wlzs1432/p/11266625.html
今日推荐