码迷,mamicode.com
首页 > 其他好文 > 详细

Miller-Rabin大素数测试模板

时间:2015-12-03 11:27:50      阅读:204      评论:0      收藏:0      [点我收藏+]

标签:

根据费马小定理:

对于素数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; }

 

Miller-Rabin大素数测试模板

标签:

原文地址:http://www.cnblogs.com/chenhuan001/p/5015412.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!