zoukankan      html  css  js  c++  java
  • 大素数测试的Miller-Rabin算法

    Miller-Rabin算法本质上是一种概率算法,存在误判的可能性,但是出错的概率非常小。出错的概率到底是多少,存在严格的理论推导。

    一、费马小定理

    假如p是质数,且gcd(a,p)=1,那么 a(p-1)≡1(mod p)

    如果存在a<p,且a(p-1) % p != 1,则p肯定不是素数。

    二、有限域上的平方根定理

    三、Miller-Rabin算法

    对于一个大数n,判断n是不是素数的时候,可以先考虑a(n-1)≡ 1(mod n)

    对于n-1,一定可以拆分成2s+d:

    可以从x = ad开始,依次平方s次,每次平方的时候模上n,按照之前的平方根定理,如果模上n的结果为1的话,那么x一定是1,或者是n-1,如果不满足则不是素数,x=x2,再次循环。

    每次随机选一个在2-n-1的数字作为a,可以重复测试。

    由于mod上的是n,n是一个大数,所以快速幂中的乘法,需要用快速加法来实现。不然就算模上之后再相乘也会溢出。

     1 #include<iostream>
     2 #include<ctime>
     3 #include<algorithm>
     4 using namespace std;
     5 typedef long long ll;
     6 const int maxn = 1000000+10;
     7 ll mul(ll a, ll b, ll m)
     8 //求a*b%m
     9 {
    10     ll ans = 0;
    11     a %= m;
    12     while(b)
    13     {
    14         if(b & 1)ans = (ans + a) % m;
    15         b /= 2;
    16         a = (a + a) % m;
    17     }
    18     return ans;
    19 }
    20 ll pow(ll a, ll b, ll m)
    21 //a^b % m
    22 {
    23     ll ans = 1;
    24     a %= m;
    25     while(b)
    26     {
    27         if(b & 1)ans = mul(a, ans, m);
    28         b /= 2;
    29         a = mul(a, a, m);
    30     }
    31     ans %= m;
    32     return ans;
    33 }
    34 bool Miller_Rabin(ll n, int repeat)//n是测试的大数,repeat是测试重复次数
    35 {
    36     if(n == 2 || n == 3)return true;//特判
    37     if(n % 2 == 0 || n == 1)return false;//偶数和1
    38 
    39     //将n-1分解成2^s*d
    40     ll d = n - 1;
    41     int s = 0;
    42     while(!(d & 1)) ++s, d >>= 1;
    43     srand((unsigned)time(NULL));
    44     for(int i = 0; i < repeat; i++)//重复repeat次
    45     {
    46         ll a = rand() % (n - 3) + 2;//取一个随机数,[2,n-1)
    47         ll x = pow(a, d, n);
    48         ll y = 0;
    49         for(int j = 0; j < s; j++)
    50         {
    51             y = mul(x, x, n);
    52             if(y == 1 && x != 1 && x != (n - 1))return false;
    53             x = y;
    54         }
    55         if(y != 1)return false;//费马小定理
    56     }
    57     return true;
    58 }
    59 int main()
    60 {
    61     int T;
    62     cin >> T;
    63     ll n;
    64     while(T--)
    65     {
    66         cin >> n;
    67         if(Miller_Rabin(n, 50))cout<<"Yes"<<endl;
    68         else cout<<"No"<<endl;
    69     }
    70 }
  • 相关阅读:
    codeforces 1349 A 思维
    codeforces 1358 D 尺区
    codeforces 1251D 二分+贪心
    codeforces 1260 D 二分
    codeforces 1167B 交互ez
    volatile
    计算多级集合/树/部门树的深度
    Java学习路线-知乎
    day06
    day01_虚拟机与主机之间ip配置
  • 原文地址:https://www.cnblogs.com/fzl194/p/9046117.html
Copyright © 2011-2022 走看看