这里将介绍4中方法筛选素数,并统一输出运行时间进行比较,统一用标记法,统一筛选10000005内的素数
一、暴力
也就是最原始的方法,从2遍历到sqrt(n)如果有一个数能被n整除,就不是素数,结果输出4.887秒,太耗时
#include<bits/stdc++.h>
#include<time.h>
#define maxn 10000005
using namespace std;
bool prime[maxn];
void Screening()
{
prime[0]=prime[1]=0;
for(int i=2;i<maxn;i++)
{
bool flag=0;
int lim=(int)sqrt((double)i)+0.5;
for(int j=2;j<lim;j++)
if(i%j==0)
{
flag=1;
break;
}
if(flag==0) prime[i]=1;
}
}
int main()
{
clock_t start,finish;
double totaltime;
start=clock();//开始计时
Screening();
finish=clock();//结束
totaltime=(double)(finish-start)/CLOCKS_PER_SEC;//计算
cout<<totaltime<<"秒!"<<endl;//4.887秒!
return 0;
}
二、普通筛选法
先将偶数标记,对于奇数,筛去所有倍数,运行时间为0.321秒!
#include<bits/stdc++.h>
#include<time.h>
#define maxn 10000000005
using namespace std;
bool prime[maxn]; //如果是0,就是是素数
void Screening()
{
int lim=(int)sqrt((double)maxn+0.5);
for(int i=4;i<=maxn;i+=2) prime[i]=1;
for(int j=3;j<lim;j+=2)
for(int k=j+j;k<=maxn;k+=j) prime[k]=1;
}
int main()
{
clock_t start,finish;
double totaltime;
start=clock();//开始计时
Screening();
finish=clock();//结束
totaltime=(double)(finish-start)/CLOCKS_PER_SEC;//计算
cout<<totaltime<<"秒!"<<endl;//0.321秒!
return 0;
}
三、埃拉托色尼(Eratosthenes)筛法
筛去所有素数的倍数,运行时间为0.123秒!
#include<bits/stdc++.h>
#include<time.h>
#define maxn 10000005
using namespace std;
bool prime[maxn]; //如果是0,就是是素数
void Screening()
{
int lim=(int)sqrt((double)maxn+0.5);
for(int i=2;i<lim;i++)
if(!prime[i])
for(int j=i*i;j<maxn;j+=i)
prime[j]=1;
}
int main()
{
clock_t start,finish;
double totaltime;
start=clock();//开始计时
Screening();
finish=clock();//结束
totaltime=(double)(finish-start)/CLOCKS_PER_SEC;//计算
cout<<totaltime<<"秒!"<<endl;//0.123秒!
return 0;
}
四、线性筛(欧拉法)
首先,根据欧拉公式,任何合数(非素数)都能表示成一系列素数的积。 上面的筛选法中,有些数会被重复标记很多次,比如12,会被2,3,4,6的倍数标记,欧拉筛就避免了这种情况。
利用了每个合数必有一个最小素因子,每个合数仅被它的最小素因子筛去正好一次。所以为线性时间。
代码中体现在: if(i%prime[j]==0)break;
prime数组 中的素数是递增的,当 i 能整除 prime[j],那么 i*prime[j+1] 这个合数肯定被 prime[j] 乘以某个数筛掉。
因为i中含有prime[j], prime[j] 比 prime[j+1] 小。接下去的素数同理。所以不用筛下去了。
在满足i%prme[j]==0这个条件之前以及第一次满足改条件时,prime[j]必定是prime[j]*i的最小因子。
#include<bits/stdc++.h>
#define M 10000005
using namespace std;
int prime[M];
bool vis[M];
void screening()
{
vis[0]=vis[1]=true;
int cnt=0;
for(int i=2;i<M;i++)
{
if(!vis[i]) prime[cnt++]=i;
for(int j=0;j<cnt&&i*prime[j]<M;j++)
{
vis[i*prime[j]]=true;
if(i%prime[j]==0) break;
}
}
}
int main()
{
screening();
int n,m;
cin>>n>>m;
while(m--)
{
int x;
cin>>x;
if(vis[x])
cout<<"No"<<endl;
else
cout<<"Yes"<<endl;
}
return 0;
}
数据量大时候会很快