Miller Labin 素性检验

学了这么久复习一下。

例题HDU2138

给你一堆很大的数字,怎么判断它们是不是质数?

真鸡儿简单,试除法啊!

如果数字很大的话,显然根号的试除法也能试到宇宙的尽头...所以我们要学新算法。

费马小定理:

首先是费马小定理.假如a是一个整数p是一个质数,那么a^{p}-a是p的倍数,可以表示为 a^{p} \equiv a(mod p),如果a不是p的倍数,这个定理也可以写成a^{p-1}\equiv 1 (mod p)

Wiki上的这个证明很给力

那么现在我们有如果p是素数,那么一定满足 a^{p-1}\equiv 1 (mod p)。但是如果反过来呢?如果a^{p-1}\equiv 1 (mod p),那么p是否一定是一个质数呢?答案是否定的。有一类数叫卡迈克尔数,这类数都是合数,561是最小的卡迈克尔数,假设a与561互质,则a^{{560}}被561除都余1。

所以,如果对于一个p,有(a,p)=1,且a^{p-1}\equiv 1 (mod p),我们就只能说p是有一定概率是一个素数。那么我们要怎么样来减小判断失误的概率呢?为了解决这个问题,我们又引入了二阶检测定理。

二阶检测定理:

            如果对于素数p,0<x<p,x{^2}\equiv 1(mod p)的解为x=1orx=p-1。(证明trivial)

​
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<map>
#include<stack>
#include<string>
#include<algorithm>
typedef unsigned long long ll;
using namespace std;
ll mulmod(ll a,ll b,ll mod){
    ll ans=0;
    while(b){
        if(b&1) ans=(ans+a)%mod;
        b>>=1;
        a=(a*2)%mod;
    }
    return ans;
}
ll fastpowmod(ll a,ll b,ll mod){
    ll ans=1;
    while(b){
        if(b&1) ans=mulmod(a,ans,mod);
        b>>=1;
        a=mulmod(a,a,mod);
    }
    return ans;
}

bool miller_rabin(ll a,ll n){
    if(n==2||n==a) return true;
    if(!(n&1)) return false;
    ll s=n-1;
    while(!(s&1)) s>>=1;
    ll now = fastpowmod(a,s,n);
    if(now==1||now==n-1) return true;
    while(s<n-1){
        s<<=1;
        now=fastpowmod(now,2,n);
        if(now==n-1) return true;
    }
    return false;
}

bool isprimer(ll n){
    ll a[]={2,3,5,7,11,13,41,67};
    for(int i=0;i<6;i++){
        if(miller_rabin(a[i],n)==false){
            return false;
        }
    }
    return true;

}
int main(){
    ll n;
    while(cin>>n){
        cout<<isprimer(n)<<endl;
    }
    return 0;
}

​

猜你喜欢

转载自blog.csdn.net/ffscas/article/details/86634848
今日推荐