费马小定理: p是质数,则 0<x<p 满足 ( x^(p-1) )%p=1
二次探测定理: 0<x<p p为质数 x^2%p=1 则 x=p-1或x=1
一次的miller-rabin
如果p是质数,则偶数 p-1=m*2^q。求出m(奇数)和q。
然后先计算x=x^m的值.
然后进行q次计算
计算temp= (x)^2%p的值
temp=1 x!=1 和x!=p-1 ,p就不是素数 。不满足二次探测
temp!=1 把取模后的值作为新的x
循环计算直到k=q的时候
这个时候 x^(p-1)=x^(m*2^q) 使用 费马小定理判断 是否是合数
#include <stdlib.h>
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int s=20;///探测次数
int mul(int a,int n,int nn)
{
int ans=0,temp;
while(n)
{
if(n&1) ans=(ans+a)%nn;
a=(a+a)%nn;
n>>=1;
}
return ans;
}
int pow(int a,int n,int nn)
{
int ans=1,temp;
while(n)
{
if(n&1) ans=mul(ans,a,nn);///这边容易爆int
a=mul(a,a,nn);
n>>=1;
}
return ans;
}
bool miller(int a,int x,int n,int k)
{
int ret=pow(a,x,n);
int last=ret;
for(int i=0;i<k;i++)
{
ret=mul(ret,ret,n);///这边是* 写成^
if(ret==1&&last!=1&&last!=n-1) return true;
last=ret;
}
if(ret!=1) return true; ///费马小定理 不是素数
return false;///素数
}
bool ini(int n)
{
if(n<2) return false;
if(!(n&1)&&n!=2) return false;
int k=0;
int x=n-1;
while((x&1)==0) {k++;x>>=1;}///x=n-1=m*2^k
for(int i=0;i<s;i++)
{
int a=rand()%(n-1)+1;
//printf("->%d",a);
if(miller(a,x,n,k)) return false;///不是素数
}
return true;///素数
}
Miller测试进行k次,将合数当成素数处理的错误概率最多不会超过4^(-k).