• Miller-Rabin大素数测试模板


    根据费马小定理:

    对于素数n,a(0<a<n),a^(n-1)=1(mod n)

    如果对于一个<n的正整数a,a^(n-1)!=1(mod n),则n必不是素数。

    然后就可以随机生成  <n的数,如果都满足,那n就极有可能是素数。

    看书上说,一次素数测试的成功率是 3/4,也就是失败率是1/4,那测m次是错误的概率为:(1/4)^m.可见m稍微大一点就基本不会出错。

    但是还有一种数叫,卡迈克尔数。

    卡迈克尔数: 一个合数n,对所有满足 gcd(b,n)=1的正整数b都有b^(n-1)=1(mod n) 成立。

    因为这种数的存在,在检测这些数是否是素数时可能正确率就会降低很多。

    这是我们可以采用二次探测:

    如果p是一个素数,且 0<x<p , 则方程x^2=1(mod p) 的解为x=1或x=p-1

    换句话说,如果发现x^2=1(mod p) 成立且x!=1&&x!=p-1,则p不为素数。

    对照着卡迈克尔数,我们可以发现卡迈克尔数是有很大可能无法通过二次探测的。 因为对于某个数为b, 如果gcd(b,n)=1且b^(n-1)=1(mod n)成立,如果b^( (n-1)/2 )不为1和n-1则n不为素数。

    在比赛中,基本可以看做是 O(1)的素数检测。 但是因为要一定次数随机,速度问题也是要考虑的。

    //输入一个long long 范围内的素数,是素数返回true,否则返回false。定义检测次数TIMES,错误率为(1/4)^TIMES
    #define
    TIMES 10 long long GetRandom(long long n) { //cout<<RAND_MAX<<endl; long long num = (((unsigned long long)rand() + 100000007)*rand())%n; return num+1; } long long Mod_Mul(long long a,long long b,long long mod) { long long msum=0; while(b) { if(b&1) msum = (msum+a)%mod; b>>=1; a = (a+a)%mod; } return msum; } long long Quk_Mul(long long a,long long b,long long mod) { long long qsum=1; while(b) { if(b&1) qsum=Mod_Mul(qsum,a,mod); b>>=1; a=Mod_Mul(a,a,mod); } return qsum; } bool Miller_Rabin(long long n) { if(n==2||n==3||n==5||n==7||n==11) return true; if(n==1||n%2==0||n%3==0||n%5==0||n%7==0||n%11==0) return false; int div2=0; long long tn=n-1; while( !(tn%2) ) { div2++; tn/=2; } for(int tt=0;tt<TIMES;tt++) { long long x=GetRandom(n-1); //随机得到[1,n-1] if(x==1) continue; x=Quk_Mul(x,tn,n); long long pre=x; for(int j=0;j<div2;j++) { x = Mod_Mul(x, x, n); if(x==1&&pre!=1&&pre!=n-1) return false; pre=x; } if(x!=1) return false; } return true; }
  • 相关阅读:
    离线数仓 建模、表的类型分类
    获取每个部门中当前员工薪水最高的相关信息
    dwd层 维度退化 的作用
    单例模式懒汉式
    反汇编命令使用
    RabbitMQ实战高级特性
    初步理解MySQL的gap锁
    【java并发系列】Controller是线程安全吗_ 安全方式如何
    mysql_14_count(*)为什么这么慢
    MySQL 通过Docker搭建主从同步
  • 原文地址:https://www.cnblogs.com/chenhuan001/p/5015412.html
Copyright © 2020-2023  润新知