• 51nod 1186 Miller-Rabin素数测试


    费尔马小定理:如果p是一个素数,且0<a<p,则a^(p-1)%p=1.利用费尔马小定理,对于给定的整数n,可以设计素数判定算法,

            通过计算d=a^(n-1)%n来判断n的素性,当d!=1时,n肯定不是素数,当d=1时,n   很可能是素数.

    二次探测定理:如果是素数,且,则方程的解为

            利用二次探测定理,可以再利用费尔马小定理计算a^(n-1)%n的过程 中增加对整数n的二次探测,

           一旦发现违背二次探测条件,即得出n不是素数的结论.

    先贴出long long 范围的代码:

     1 /*
     2 long long 范围的Miller-Rabin素数测试
     3 */
     4 
     5 #include <iostream>
     6 #include <stdio.h>
     7 #include <string.h>
     8 #include <stdlib.h>
     9 #include <time.h>
    10 #define ll long long
    11 using namespace std;
    12 
    13 //计算a*b%mod
    14 ll mod_mul(ll a, ll b, ll n){
    15     ll cnt = 0LL;
    16     while(b){
    17         if(b&1LL) cnt = (cnt+a)%n;
    18         a=(a+a)%n;
    19         b >>= 1LL;
    20     }
    21     return cnt;
    22 }
    23 //计算a^b%mod
    24 ll mod_exp(ll a, ll b, ll n){
    25     ll res = 1LL;
    26     while(b){
    27         if(b&1LL) res = mod_mul(res,a,n);
    28         a = mod_mul(a,a,n);
    29         b >>= 1LL;
    30     }
    31     return res;
    32 }
    33 //Miller-Rabin测试,测试n是否为素数
    34 bool Miller_Rabin(ll n, int respat){
    35     if(n==2LL || n==3LL || n==5LL || n==7LL || n==11LL) return true;
    36     if(n==1 || !(n%2) || !(n%3) || !(n%5) || !(n%7) || !(n%11)) return false;
    37     
    38     int k = 0;
    39     ll d = n-1; //要求x^u%n 不为1一定不是素数
    40     
    41     while(!(d&1LL)){
    42         k++; d >>= 1LL;
    43     }
    44     srand((ll)time(0));
    45     for(int i = 0; i < respat; i ++) {
    46         ll a = rand()%(n-2)+2;     //在[2,n)中取整数
    47         ll x = mod_exp(a,d,n);
    48         ll y = 0LL;
    49         for(int j = 0; j < k; j ++){
    50             y = mod_mul(x,x,n);
    51             if(1LL==y && 1LL!=x && n-1LL!=x)return false; //二次探测定理,这里如果y = 1则x必须等于 1
    52                                                           //或n-1,否则可以判断不是素数
    53             x = y;
    54         }
    55         if(1LL != y) return false;     //费马小定理
    56     }
    57     return true;
    58 }
    59 int main(){
    60     int n;
    61     cin>>n;
    62     if(Miller_Rabin(n,5))cout << "Yes
    ";
    63     else cout << "No
    ";
    64     return 0;
    65 }

    当数字达到10^30时,就要用到大数了,贴下模板。

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <cstdlib>
      4 
      5 #define MAXL 4
      6 #define M10 1000000000
      7 #define Z10 9
      8 
      9 const int zero[MAXL - 1] = {0};
     10 
     11 struct bnum{
     12     int data[MAXL]; //  断成每截9个长度
     13     
     14     //  读取字符串并转存
     15     void read(){
     16         memset(data, 0, sizeof(data));
     17         char buf[32];
     18         scanf("%s", buf);
     19         int len = (int)strlen(buf);
     20         int i = 0, k;
     21         while (len >= Z10){
     22             for (k = len - Z10; k < len; ++k){
     23                 data[i] = data[i] * 10 + buf[k] - '0';
     24             }
     25             ++i;
     26             len -= Z10;
     27         }
     28         if (len > 0){
     29             for (k = 0; k < len; ++k){
     30                 data[i] = data[i] * 10 + buf[k] - '0';
     31             }
     32         }
     33     }
     34     
     35     bool operator == (const bnum &x) {
     36         return memcmp(data, x.data, sizeof(data)) == 0;
     37     }
     38     
     39     bnum & operator = (const int x){
     40         memset(data, 0, sizeof(data));
     41         data[0] = x;
     42         return *this;
     43     }
     44     
     45     bnum operator + (const bnum &x){
     46         int i, carry = 0;
     47         bnum ans;
     48         for (i = 0; i < MAXL; ++i){
     49             ans.data[i] = data[i] + x.data[i] + carry;
     50             carry = ans.data[i] / M10;
     51             ans.data[i] %= M10;
     52         }
     53         return  ans;
     54     }
     55     
     56     bnum operator - (const bnum &x){
     57         int i, carry = 0;
     58         bnum ans;
     59         for (i = 0; i < MAXL; ++i){
     60             ans.data[i] = data[i] - x.data[i] - carry;
     61             if (ans.data[i] < 0){
     62                 ans.data[i] += M10;
     63                 carry = 1;
     64             }
     65             else{
     66                 carry = 0;
     67             }
     68         }
     69         return ans;
     70     }
     71     
     72     //  assume *this < x * 2
     73     bnum operator % (const bnum &x){
     74         int i;
     75         for (i = MAXL - 1; i >= 0; --i){
     76             if (data[i] < x.data[i]){
     77                 return *this;
     78             }
     79             else if (data[i] > x.data[i]){
     80                 break;
     81             }
     82         }
     83         return ((*this) - x);
     84     }
     85     
     86     bnum & div2(){
     87         int  i, carry = 0, tmp;
     88         for (i = MAXL - 1; i >= 0; --i){
     89             tmp = data[i] & 1;
     90             data[i] = (data[i] + carry) >> 1;
     91             carry = tmp * M10;
     92         }
     93         return *this;
     94     }
     95     
     96     bool is_odd(){
     97         return (data[0] & 1) == 1;
     98     }
     99     
    100     bool is_zero(){
    101         for (int i = 0; i < MAXL; ++i){
    102             if (data[i]){
    103                 return false;
    104             }
    105         }
    106         return true;
    107     }
    108 };
    109 
    110 void mulmod(bnum &a0, bnum &b0, bnum &p, bnum &ans){
    111     bnum tmp = a0, b = b0;
    112     ans = 0;
    113     while (!b.is_zero()){
    114         if (b.is_odd()){
    115             ans = (ans + tmp) % p;
    116         }
    117         tmp = (tmp + tmp) % p;
    118         b.div2();
    119     }
    120 }
    121 
    122 void powmod(bnum &a0, bnum &b0, bnum &p, bnum &ans){
    123     bnum tmp = a0, b = b0;
    124     ans = 1;
    125     while (!b.is_zero()){
    126         if (b.is_odd()){
    127             mulmod(ans, tmp, p, ans);
    128         }
    129         mulmod(tmp, tmp, p, tmp);
    130         b.div2();
    131     }
    132 }
    133 
    134 bool MillerRabinTest(bnum &p, int iter){
    135     int  i, small = 0, j, d = 0;
    136     for (i = 1; i < MAXL; ++i){
    137         if (p.data[i]){
    138             break;
    139         }
    140     }
    141     if (i == MAXL){
    142         // small integer test
    143         if (p.data[0] < 2){
    144             return  false;
    145         }
    146         if (p.data[0] == 2){
    147             return  true;
    148         }
    149         small = 1;
    150     }
    151     if (!p.is_odd()){
    152         return false;   //  even number
    153     }
    154     bnum a, s, m, one, pd1;
    155     one = 1;
    156     s = pd1 = p - one;
    157     while (!s.is_odd()){
    158         s.div2();
    159         ++d;
    160     }
    161     
    162     for (i = 0; i < iter; ++i){
    163         a = rand();
    164         if (small){
    165             a.data[0] = a.data[0] % (p.data[0] - 1) + 1;
    166         }
    167         else{
    168             a.data[1] = a.data[0] / M10;
    169             a.data[0] %= M10;
    170         }
    171         if (a == one){
    172             continue;
    173         }
    174         
    175         powmod(a, s, p, m);
    176         
    177         for (j = 0; j < d && !(m == one) && !(m == pd1); ++j){
    178             mulmod(m, m, p, m);
    179         }
    180         if (!(m == pd1) && j > 0){
    181             return false;
    182         }
    183     }
    184     return true;
    185 }
    186 
    187 int main(){
    188     bnum x;
    189     
    190     x.read();
    191     puts(MillerRabinTest(x, 5) ? "Yes" : "No");
    192     
    193     return 0;
    194 }
  • 相关阅读:
    /dev/null
    useradd
    linux防火墙
    安装ntp服务同步服务器时间
    使用WTM框架项目的部署遇到的问题及解决方式
    .net5 winform 打开文件夹
    maven打包命令
    url.openconnection() 设置超时时间
    java判断http地址是否连通
    解决 curl: (35) Encountered end of file
  • 原文地址:https://www.cnblogs.com/xingkongyihao/p/7200338.html
Copyright © 2020-2023  润新知