Miller–Rabin

作者: dachengquan | 来源:发表于2020-08-04 16:04 被阅读0次

Miller–Rabin算法用于检测大素数,时间复杂度是O(k\log^3 n)
使用费马小定理和二次探测检测一个数是否是质数。a^{p-1} \equiv 1 \pmod{p}当p是质数时,这个公式成立。但是这个公式成立p不一定是质数。因为有些合数,对于特定的a同样得到这个结果。其中有一类数无论a是什么都满足这个公式,例如561。如果不存在这样的数选择多次不同的a进行验证,使用费马小定理就可以检测出一个数是否是质数。
二次探测定理:如果p是素数 ,x^2\equiv1\pmod p的解是x\equiv 1 \pmod porx\equiv -1 \pmod p
证明过程就是
p\mid x^2-1
p\mid (x-1)(x+1),p|(x-1)p|(x+1)都能使这个式子成立。而x在1到p范围内的解只有1和p-1。

Miller-Rabin算法流程

给定一个N判断是否是整数,将N-1分解为2^t *d的形式。
我们要判断对于N来说是否能使费马小定理成立。随机选择一个a,1<a<p
a^{N-1} = a^{d*2^t} = (a^d)^{2^t}\equiv 1\pmod p费马小定理告诉我们如果N是质数最后结果模p同余1。计算a^{N-1}的过程中,可以分为计算a^d,然后对a^d进行t次平方,第二步的过程我们可以使用二次探测定理验证。

举例子:一个质数561 计算N-1 = 560

分解560 = 2^4 *35
2^{35} \equiv 263 \pmod {561}
(2^{35})^2 \equiv 166 \pmod {561}
(2^{35})^4 \equiv 67 \pmod {561}
(2^{35})^8 \equiv 1 \pmod {561}
根据二次探测定理可知p不是质数。
67^2 \equiv 1 \pmod {561}
67^2 -1\equiv 0 \pmod {561}
(67-1)(67+1)\equiv 0 \pmod {561}
66*68\equiv 0 \pmod {561}
561|66*68说明66*68拥有561的全部质因数,66<561并且68<561,所以561的质因数必定来自66的一部分和68的一部分。

a如何选取?

通常应该取随机值,但是有人测试过在下面的范围取固定的几个a就可以了。
如果n <2,047,则测试a = 2 就足够了;
如果n <1,373,653,则测试a = 2和3 就足够了;
如果n <9,080,191,则测试a = 31和73 就足够了;
如果n <25,326,001,则足以测试a = 2、3和5;
如果n <3,215,031,751,测试a = 2、3、5 和7 就足够了;
如果n <4,759,123,141,测试a = 2、7和61 就足够了;
如果n <3,474,749,660,383,测试a = 2、3、5、7、11 和13 就足够了;
如果n <341,550,071,728,321,则足以测试a = 2、3、5、7、11、13 和17。
如果n <3,825,123,056,546,413,051,则足以测试a = 2、3、5、7、11、13、17、19 和23
随机选择a,为了确保正确率通常选择的k比较高,我们知道有以上结论,每次测试直接选择前几个质数就可以了。当我们的质数选择10时,已经可以测试long long范围内的数了。
Miller-Rabin时间复杂度是O(k\log^3 n)k是选取a的次数。

#include<bits/stdc++.h>
#define ll long long 
#define i128 __int128
using namespace std;
ll n;
int primes[19]={2,3,5,7,11,13,17,19,23,29,31,37};
ll poww(ll a,ll b,ll c){
    ll ans=1;i128 base=a;
    while(b){
        if(b&1)ans=ans*base%c;
        base=base*base%c;
        b>>=1;
    }
    return ans;
}
bool miller_rabin(ll n){
    for(int i=0;i<=8;i++){
        if(primes[i]==n)return 1;
        else if(primes[i]>n)return 0;
        ll t=poww(primes[i],n-1,n),x=n-1;
        if(t!=1)return 0;
        while(t==1&&x%2==0){
            x/=2;
            t=poww(primes[i],x,n);
            if(t!=1&&t!=n-1)return 0;
        }
    }
    return 1;
}
int main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    while(cin>>n){
         if(miller_rabin(n))puts("Y");else puts("N");
    }
    return 0;
}

使用了__int128省去了自己写快速乘法的时间。
判定1e18的质数

相关文章

  • Miller–Rabin

    Miller–Rabin算法用于检测大素数,时间复杂度是使用费马小定理和二次探测检测一个数是否是质数。当p是质数时...

  • Miller-Rabin

    http://miller-rabin.appspot.com/

  • Miller-Rabin素数测试

    转载自Matrix大牛一个数是素数(也叫质数),当且仅当它的约数只有两个——1和它本身。规定这两个约数不能相同,因...

  • Miller-Rabin素数测试

    费马小定理:对于素数p和任意整数a,有ap ≡ a(mod p)(同余)。反过来,满足ap ≡ a(mod p),...

  • 判断一个数是否是素数

    问题 如题 思路 首先太暴力的就不谈,会折寿,有一个强伪证的算法(strong liar)Miller Rabin...

  • Miller-Rabin(米勒罗宾)素性测试

    算法思想 对于大于2的素数n,将n-1拆分为 准确性 所有的奇合数都有很多的a满足"witness"的条件,不过目...

  • Python 进行高精度运算

    gmpy2是Python的一个扩展库,可以进行高精度运算,适用于Miller-Rabin素数测试算法,大素数生成,...

  • 数学知识

    一、数论 首先需要掌握质数的定义,判断一个数是否是质数的试除法、Miller–Rabin等。学习筛法,求出1~N之...

  • 子字符串查找(4)——Rabin-Karp算法

    一、定义 Rabin-Karp算法,是由M.O.Rabin和R.A.Karp发明的一种基于散列的字符串查找算法。通...

  • String Matching Algorithm

    See more on github String Matching algorithm Rabin-Karp W...

网友评论

    本文标题:Miller–Rabin

    本文链接:https://www.haomeiwen.com/subject/pluurktx.html