素数判断
bool is_prime(int u) {
if (u == 0 || u == 1)return false;
if (u == 2)return true;
if (u % 2 == 0)return false;
for (int i = 3; i <= sqrt(u); i += 2)
if (u%i == 0)return false;
return true;
}
普通筛法
时间复杂度是 O(nloglogn),不足之处在于一个合数可能被筛选多次。
#include<bits/stdc++.h>
using namespace std;
const int N = 2000005;
int prime[N], num = 0;//prime存素数
bool p[N] = { 0 };//p存是否被筛除
void find_prime()
{
p[0] = p[1] = true;
for (int i = 2; i < N; i++)//筛选2~maxn内的素数
{
if (p[i] == false)//没被筛除的(即为素数)记为false,被筛除的为true
{
prime[num++] = i;//i为素数加入数组
for (int j = i + i; j < N; j += i)//筛除i的倍数
{
p[j] = true;
}
}
}
}
线性筛
时间复杂度为 O(n),原因在于每个合数保证只被它最小的那个质因子筛选。关键代码在第 10,11 行,因为如果 i 能整除 prime[j],那么 i 肯定是个合数,且 i 中有质因子肯定小于等于 prime[j],所以到此就可以停止了,因为后面的 prime[]会比 i 小的那个质因子要大。
const int N = 2000005;
int prime[N], num = 0;//prime存素数
bool p[N] = { 0 };//p存是否被筛除
void find_prime() {
p[0] = p[1] = 1;
for (int i = 2; i < N; i++) {
if (!p[i])
prime[num++] = i;
for (int j = 0; j < num && prime[j] * i < N; j++) {
p[i*prime[j]] = 1;
if (i % prime[j] == 0)
break;
}
}
}