素数判定(含Miller-Rabin素数判断法)

https://blog.csdn.net/ltyqljhwcm/article/details/53045840


计算小于n的所有素数:时间复杂度

#include
using namespace std;
#define N 1001
bool p[N]={0};
// 注意,如果是a[100]={0}是所有的值为0,而a[100]={1}则是只有第一个值为1;
// 为了初始化方便,false为素数,true为非素数
// 算法复杂度 O(nloglogn)
int pNum=0;
bool is_prime(int a){
   if(a==1){
     return false;
   }
   //long long sqr=(long long)sqrt(1.0*a);
   for(int i=2;i*i<=a;i++){
     if(a%i==0){
       return false;
     }
   }
   return true;
}
// 利用小于它的素数计算是否成立,用于求解小于n的所有素数
void find_prime(int max){
  int i=0,j=0;
  p[0]=p[1]=true;
  for(i=2;i<=max;i++){
    if(p[i]==false){
      if(is_prime(i)){
          // 对所有与该素数成整数倍关系的标记为true(非素)
          for(j=i+i;j<=max;j+=j){
              p[j]=true;
          }
      }
      else{
        p[i]=true;
      }
    }
  }
}
int main(){
  int a=13,i;
  find_prime(a);
  for(i=0;i

利用空间换时间的基于素数表的素数计算:

#include
using namespace std;
#define N 1001
bool p[N]={false};

// 10^5以内可以接受。算法复杂度 nlog(n)
bool is_prime(int a){
   if(a==1){
     return false;
   }
   //long long sqr=(long long)sqrt(1.0*a);
   for(int i=2;i*i<=a;i++){
     if(a%i==0){
       return false;
     }
   }
   return true;
}
void find_prime(int max){
  int i=0;
  for(i=2;i<=max;i++){
    if(is_prime(i)){
        p[i]=true;
    }
  }
}
int main(){
  int a=13,i;
  find_prime(a);
  for(i=0;i

以上都是常规算法,下面是最快的算法(又回到了被数论统治的年代...):

Miller_Rabin(米勒-拉宾)素数判别法:时间复杂度log2(n)

费马小定理:设p 是素数,a与p互素,则 .
这个定理反过来用,p 几乎(有非常小的概率不是,原因如下)一定是素数。

如果一个数不满足费马小定理,那么这个数必定是合数,但是如果这个数满足我们就没有办法确定是不是合数还是素数了,因为历史上有一种非常神秘的数的存在——卡密歇尔数,这类数我们也叫伪素数。无论我们选择多少个素数a,都无法排除Carmichael Number。

证明:

  1. 前引:p是素数,且(0

所以且,且的话,p肯定不是素数。

  1. 先判断是否是奇数,偶数直接挂。

  2. 因为n是奇数,所以,必然r=n-1肯定可以分为=,相当于把拆成

  3. 因为当成立时,若才行,因为此时,能继续分拆为但是不行因为没法拆成

  • 若n是奇合数,则在区间0
核心部分的伪代码:
// 检测num是否是素数
    for(i=0;i<20;i++){
        c=num-1;
        // 生成20个大于等于2小于num的随机数,从而保证错误率低于(1/4)^20
        long long r=rand()%(num-2)+2;
        long long y=aPowb(r,c,num);
        if(y!=1){
            return 404;
            // 首先得保证a^(num-1)%num==1
        }
        for(j=0;j

代码:需要结合我的快速幂

#include
#include
#include
#include
#include
#include
#include
#include 
using namespace std;
typedef long long LL;
LL aPowb(long long a,long long p,long long b){
    if(p==0){
        return 1;
    }
    if(p&1){
        // 奇数
        long long g=aPowb(a,p/2,b);
        return ((a*g%b)*g)%b;
    }
    else{
        long long g=aPowb(a,p/2,b);
        return (g*g)%b;
    }
}
bool prime(int num){
    if(num&1!=1||num==1){
        return false;
    }
    if(num==2){
        return true;
    }
    int k=0,i=0,j=0;
    int c=num-1;
    while((c&1)==0){
        c>>=1;
        k++;
        // k记录a*2^k中k的次数
    }
    for(i=0;i<20;i++){
        c=num-1;
        // 20次随机数保证客观
        long long r=rand()%(num-2)+2;
        long long y=aPowb(r,c,num);
        if(y!=1){
            return false;
        }
        // cout<0){
            j--;
            c/=2;
            y=aPowb(r,c,num);
            // cout<>input;
    cout<

你可能感兴趣的:(素数判定(含Miller-Rabin素数判断法))