1.基本方法
输出(n)以内的所有质数,遍历([1,n])的所有数,每个数(p)都不能被([2,p])整除,则为质数
2.初步优化
针对任意数(N),如果有一个数(p(p le sqrt{N}))是(N)的因子,则一定有(u=frac{N}{p}(ugeq sqrt{N}))也是它的因子,如果不存在(p)这样的因子,那么(N)就是质数
3.素数筛
时间复杂度:(O(n))
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
int pri[1005];
int n;
int main(){
scanf("%d",&n);
for(int i=2;i<=n;i++){
pri[i]=1;
}
for(int i=2;i<=sqrt(n)+1;i++){
if(pri[i]){
for(int j=2;j<=n/i;j++){
pri[i*j]=0;
}
}
}
for(int i=2;i<=n;i++){
if(pri[i]) printf("%d
",i);
}
return 0;
}
4
埃氏筛法
该算法时间复杂度为:(O(nloglogn))
当 (n = 10^6) 时 , 复杂度约为 (7.7 imes 10^5),优于(O(n))
//求100以内素数
#include<iostream>
#include<cstring>
#include<string>
using namespace std;
bool vis[101];//标记是否为素数
int prime[101];//储存素数
int main()
{
int n,m,j,k,i,T,t=0;
memset(vis,true,sizeof(vis));//初始化,都默认为素数
for (i=2;i<100;i++)
{
if (vis[i]==true)//如果是素数
{
prime[t++] = i;//把素数i储存进去
for (j=i+i;j<100;j+=i)//枚举素数i的倍数,然后标记为非素数
vis[j] = false;//标记为非素数
}
}
for (i=0;i<t;i++)
cout<<prime[i]<<endl;//打印答案
return 0;
}
5
质数还有一个特点,就是它总是等于 (6x-1) 或者 (6x+1),其中 x 是大于等于1的自然数。
如何论证这个结论呢,其实不难。首先 (6x) 肯定不是质数,因为它能被 (6) 整除;其次(6x+2) 肯定也不是质数,因为它还能被(2)整除;依次类推,(6x+3) 肯定能被 (3) 整除;(6x+4) 肯定能被(2) 整除。那么,就只有 (6x+1) 和 (6x+5) (即等同于(6x-1)) 可能是质数了。所以循环的步长可以设为 (6),然后每次只判断 (6)两侧的数即可。
#include <cmath>
bool isPrime(int num) {
if (num <= 3) {
return num > 1;
}
// 不在6的倍数两侧的一定不是质数
if (num % 6 != 1 && num % 6 != 5) {
return false;
}
int sqrta = sqrt(num);
for (int i = 5; i <= sqrta; i += 6) {
if (num % i == 0 || num % (i + 2) == 0) {
return false;
}
}
return true;
}