• Miller-Rabin(素数测试算法)


    【作用】

    一般素数判定方法有试除法和Miller-Rabin。试除法枚举2-√n,时间复杂度为O(√n) , 一旦n特别大,就不适合用试除法进行判定。

    这时候我们可以对其进行 Miller-Rabin 素数测试,可以大概率测出其是否为素数。

    【两个基础理论】

    (1):费马小定理:当p为质数时,有ap-1≡1(mod p).注意逆命题是假命题,比如卡迈克尔(Carmichael)数。

    对于合数满足费马小定理的数叫伪素数,

    (2):二次测探:如果p是一个素数,0<x<p,则方程x2≡1(mod p)的解为x = 1 或 x = p - 1.

     (1)对于一些常见的素数和非素数 可以直接判断。

    (2)设要测试的数为 x,我们取一个较小的质数 a,设 s,t,满足 2s * t = x - 1(其中 t 是奇数)。

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

    (4)最后我们根据费马小定律,如果最后不满足费马小定理 ,则说明 x 为合数。

    (5)多次取不同的 a 进行 Miller-Rabin 素数测试,这样可以使正确性更高

    https://blog.csdn.net/forever_dreams/article/details/82314237

    https://www.cnblogs.com/Antigonae/p/10226580.html

    int quickmul(int a , int b , int m){
        return  ((a * b - (ll)(long double)(a/m*b) * m)+m)%m ;
    }
    
    int quickpow(int a , int b , int m){
        int ans = 1 ;
        while(b){
            if(b&1) ans = quickmul(ans , a , m) ;
            b >>= 1 ;
            a = quickmul(a , a , m);
        }
        return ans ;
    }
    
    bool Miller_Rabin(int n){
        if(n == 46856248255981ll || n < 2) return false;
        if(n == 2 || n == 3 || n == 7 || n == 61 || n == 24251) return true;
        if(!(n&1) || !(n%3) || !(n%61) || !(n%24251)) return false;
        int m = n - 1 , k = 0 ;
        while(!(m&1)) k++ , m>>=1 ;// 分解2^s * t = n - 1
        rep(i , 1 , 20){
            int a = rand() % (n - 1) + 1 , x =  quickpow(a , m , n) , y;
            rep(j , 1 , k){
                y = quickmul(x , x , n);
                if(y == 1 && x != 1 && x != n - 1) return false;//二次测探
                x = y ;
            }
            if(y != 1) return false;//费马小定理
        }
        return true;
    }
    
    void solve(){
        int x ;
        cin >> x ;
        if(Miller_Rabin(x)) cout << "Yes" << endl;
        else cout << "No" << endl;
    }
    
  • 相关阅读:
    H5页面跳到安卓APP和iosAPP
    JS location.href传参及接受参数
    获取当前日期及对应星期
    前端获取当前一周时间 数组形式
    Java基础(四) Object 数组转成 String 数组
    定时任务cron表达式详解
    jquery如何删除数组中的一个元素?
    Mybatis Mapper.xml 需要查询返回List<String>
    oracle的 listagg() WITHIN GROUP () 行转列函数的使用
    如何修改Oracle中表的字段长度?
  • 原文地址:https://www.cnblogs.com/nonames/p/12431151.html
Copyright © 2020-2023  润新知