Miller–Rabin素数检测法

感觉这就是一个多次随机的算法……

算法

嗯,随机大法好,在一般判断素数中主要有这几种:暴力枚举判断法(判断一个:O(√n)),杜氏筛(O(nloglogn),欧拉筛(n)等,这里说一个随机筛法:Miller–Rabin,这玩意主要靠两条定理,一是费马小定理,二是二次探测定理,以下说一下算法流程:
对于一个p来说,
1.随即去一个a。
2.若a^(p-1)%p!=1,则这是一个合数,退出
3.若a^(p-1)%p==1,则这个数说不定是质数
4.返回1
这是一个不错的思路,然而,依旧有一些合数会被判做质数,这类数是强伪素数,所以,我们要用二次探测定理。
二次探测定理:如果p是一个素数,且0<x<p,则方程x^2≡1(mod p)的解为x=1或p-1。这就很棒了,注明对于步骤一多多益善。
上代码

#include<bits/stdc++.h>
using namespace std;
long long x;
long long power(long long a,long long b){
    long long r=1;
    a=a%x;
    while(b){
        if(b%2) r=r*a%x;
        a=a*a%x;
        b/=2;
    }
    return r%x;
}
int main(){
    cin>>x;
    if(x==1){
        printf("NO\n");
        return 0;
    }
    if(x==2){
        printf("YES\n");
        return 0;
    }
    if(x%2==0){
        printf("NO\n");
        return 0;
    }
    srand(time(NULL));
    for(int i=1;i<=1000;i++){
        long long y=rand(),k=x-1;
        if(power(y%x,x)!=y%x){
            printf("NO\n");
            return 0;
        }
        while(k==(k/2)*2){
            long long l=power(y,k);
            if(l==x-1){
                printf("YES\n");
                return 0;
            }
            if(l==1) k/=2;
            else{
                printf("NO\n");
                return 0;
            }
        }
    }
    printf("YES\n");
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sjzezwzy/article/details/80877838
今日推荐