埃氏筛选与欧氏筛选以及其它素数的快速判定
1.埃氏筛选;
时间复杂度:O(nloglogn);
思想:让找到1到n的所有素数,先假定1到n都是素数,然后
1)0不是素数,1不是素数,标记0,1为非素数;
2)从2开始,只要是素数,就将该素数的倍数都标记为非素数;
代码实现:
#include<stdio.h>
#include<stdlib.h>
int prime[100000];
int is_prime[100000];
int sieve(int n)
{
for(int i=0;i<=n;i++){
is_prime[i]=1;
}//先初始化is_prime数组均为1,表示0-n仅是素数
is_prime[0]=0;//0不是素数
is_prime[1]=0;//1不是素数
int len=0;
for(int i=2;i<=n;i++){
if(is_prime[i]==1){
//如果是素数,将其所有倍数标记为不是素数
prime[len++]=i;
for(int j=2*i;j<=n;j+=i){
is_prime[j]=0;
}
}
}
return len;//返回该区间所有素数
}
int main()
{
int n;
scanf("%d",&n);
int len=sieve(n);
for(int i=0;i<len;i++){
printf("%d",prime[i]);
if(i<len-1)printf(" ");
}
return 0;
}
2.欧氏筛选
对于非素数的正整数,(1除外),总能拆分成若干个素数积,在从1筛到这个数的过程中,该数可能会被筛出去多次,所以使用欧式筛选往往能更快。
代码实现:
#include<stdio.h>
int flag[100001];//标记是否已经被筛出
int prime[10000];//存放素数的数组
int sieve(int n)
{
int len=0;
for(int i=0;i<=n;i++){
flag[i]=0;//flag为0说明未被筛出;为1说明已经被筛出;
}
flag[0]=flag[1]=1;//0,1不是素数,直接筛出去;
for(int i=2;i<=n;i++){
if(flag[i]==0){
//如果当前最前面的未被筛出说明是素数,入表。
prime[len++]=i;
}
for(int j=0;prime[j]*i<=n;j++){
flag[prime[j]*i]=1;//标记为非素数
if(i%prime[j]==0)break;//仔细想明白此处为何是i%prime[j]==0就break!
}
}
return len;
}
int main()
{
int n;
scanf("%d",&n);
int len=sieve(n);
for(int i=0;i<len;i++){
printf("%d",prime[i]);
if(i<len-1)printf(" ");
}
return 0;
}
3.单个数的是否是素数的快速判定
代码:
int isPrime(unsigned long long int num)//速度是普通的素数判定的6倍
{
if(num==1)return 0;//1不是素数
if(num==2||num==3)return 1;//2,3是素数单独讨论
if(num%6!=5&&num%6!=1)return 0;//其余所有素数对6取余结果一定为1或5,不满足就不是素数
for(int i=2;i<sqrt(num);i+=6){
//次数i+=6,比普通的要快很多
if(num%i==0||num%(i+2)==0)return 0;
}
return 1;
}