Miller-Robbin 素数测试
2010年7月02日 18:13
如果一个数是伪素数,他几乎肯定是素数,如果一个数不是伪素数,他一定不是素数。
不断读取2~n-1的基b(s次),计算每次是否都有 exp(b,n-1)mod n == 1
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> using namespace std; #define maxn 100001 #define s 10 bool isprim[maxn]; void shai() { for(int i=0;i<maxn;i++) isprim[i]=1; int t; for(int i=2;i<=maxn/2;i++) { t=i+i; while(t<maxn) { isprim[t]=0; t+=i; } } } int modexp(int a,int b,int m) { __int64 ans=1;__int64 t=a%m; while(b) { if(b&1) { ans=(ans*t)%m; b--; } t=(t*t)%m; b>>=1; } return ans; } bool MillerRobbin(int n) { for(int i=1;i<=s;i++) { int a=rand()%(n-2)+2; if (modexp(a,n-1,n)!=1) return false; } return true; } int main() { //freopen("in.txt", "r", stdin); shai(); for(int i=3;i<maxn;i++) { if(MillerRobbin(i)!=isprim[i]) cout<<i<<endl; } }
原来的这个是抄黑书上的,貌似只是用费马小定理来检验的,下面的这个应该才是正确的吧,正确率确实很高:
bool MillerRobbin(int n) { if(n==2) return 1; else if((n&1)==0) return 0; int a,d; long long t; for(int i=0;i<s;i++) { a=rand()%(n-1)+1; d=n-1; while((d&1)==0) d>>=1; t=modexp(a,d,n); while(d!=n-1&&t!=1&&t!=n-1) { t=(t*t)% n; d<<=1; } if(t==n-1||(d&1)==1) continue; else return 0; } return 1; }