zoukankan      html  css  js  c++  java
  • Miller_Rabin 素数测试

    费马定理的逆定理几乎可以用来判断一个数是否为素数,但是有一些数是判断不出来的,因此,Miller_Rabin测试方法对费马的测试过程做了改进,克服其存在的问题。

    推理过程如下(摘自维基百科):

    摘自另一篇博文(手动滑稽):

    原理明白了,就直接上代码了(KuangBin大神的板子):

    代码思路是,

    • Miller_Rabin()函数随机选取 s 个a,a用做“基底”
    • check() 函数是用来判断x是否等于1,也就是判断a是否是n的凭证。
    • Mul_mod()函数是 快速乘 ,求 a^t % n 之后的值是否为正负一,因为两个数直接乘的话会很大,可能会爆Long Long, 因此用快速乘边乘边mod。
    • pow_mod()函数是 快速幂 ,在刚开始第一次判断 a^(n-1) % n 时会用到。 
     1 /* *************************************************
     2 * Miller_Rabin 算法进行素数测试
     3 * 速度快可以判断一个 < 2^63 的数是不是素数
     4 *
     5 **************************************************/
     6 const int S = 8; //随机算法判定次数一般 8 ∼ 10 就够了
     7 // 计算 ret = (a*b)%c
     8 //a,b,c < 2^63
     9 long long mult_mod(long long a,long long b,long long c)
    10 {
    11     a %= c;
    12     b %= c;
    13     long long ret = 0;
    14     long long tmp = a;
    15     while(b)
    16     {
    17         if(b & 1)
    18         {
    19             ret += tmp;
    20             if(ret > c)ret -= c;//直接取模慢很多
    21         }
    22         tmp <<= 1;
    23         if(tmp > c)tmp -= c;
    24         b >>= 1;
    25     }
    26     return ret;
    27 }
    28 // 计算 ret = (a^n)%mod
    29 long long pow_mod(long long a,long long n,long long mod)
    30 {
    31     long long ret = 1;
    32     long long temp = a%mod;
    33     while(n)
    34     {
    35         if(n & 1)ret = mult_mod(ret,temp,mod);
    36         temp = mult_mod(temp,temp,mod);
    37         n >>= 1;
    38     }
    39     return ret;
    40 }
    41 // 通过 a^(n − 1)=1(mod n)来判断 n 是不是素数
    42 // n − 1 = x ∗ 2 t 中间使用二次判断
    43 // 是合数返回 true, 不一定是合数返回 false
    44 bool check(long long a,long long n,long long x,long long t)
    45 {
    46     long long ret = pow_mod(a,x,n);
    47     long long last = ret;
    48     for(int i = 1; i <= t; i++)
    49     {
    50         ret = mult_mod(ret,ret,n);
    51         if(ret == 1 && last != 1 && last != n - 1)return true;//合数
    52         last = ret;
    53     }
    54     if(ret != 1)return true;
    55     else return false;
    56 }
    57 //**************************************************
    58 // Miller_Rabin 算法
    59 // 是素数返回 true,(可能是伪素数)
    60 // 不是素数返回 false
    61 //**************************************************
    62 bool Miller_Rabin(long long n)
    63 {
    64     if( n < 2)return false;
    65     if( n == 2)return true;
    66     if( (n&1) == 0)return false;//偶数
    67     long long x = n - 1;
    68     long long t = 0;
    69     while( (x&1)==0 )
    70     {
    71         x >>= 1;
    72         t++;
    73     }
    74     srand(time(NULL));/* *************** */
    75     for(int i = 0; i < S; i++)
    76     {
    77         long long a = rand()%(n - 1) + 1;
    78         if( check(a,n,x,t) )
    79             return false;
    80     }
    81     return true;
    82 }
    View Code
  • 相关阅读:
    hdu 1028 Ignatius and the Princess III (n的划分)
    CodeForces
    poj 3254 Corn Fields (状压DP入门)
    HYSBZ 1040 骑士 (基环外向树DP)
    PAT 1071 Speech Patterns (25)
    PAT 1077 Kuchiguse (20)
    PAT 1043 Is It a Binary Search Tree (25)
    PAT 1053 Path of Equal Weight (30)
    c++ 常用标准库
    常见数学问题
  • 原文地址:https://www.cnblogs.com/daybreaking/p/9853433.html
Copyright © 2011-2022 走看看