1 埃拉托斯特尼筛法
const int N = 1111111;
int isprime[N], prime[N], num; //isprime为素数筛,prime为素数表,num为表长
//埃拉托斯特尼筛法,复杂度为o(nloglogn)
void mark_table(int n) //求n以内的素数
{
num = 0;
memset(isprime, 0, sizeof(isprime));
for (int i = 2; i <= n; i++) {
if (!isprime[i]) {
prime[num++] = i;
for (int j = 2; i*j <= n; j++)
isprime[i*j] = 1;
}
}
//for (int i = 0; i < num; i++)
//cout << prime[i] << endl;
}
2 区间筛法,用于求解[a,b)内素数的个数
typedef long long ll;
const int maxn = 1000005;
bool is_prime[maxn];
bool is_prime_small[maxn];
ll prime[maxn];
ll prime_num = 0;
#define max(a,b) (a>b?a:b)
//对区间[a,b)内的整数执行筛法,is_prime[i-a]=true --- 表示i是素数 注意这里下标偏移了a,所以从0开始。
void segment_sieve(ll a, ll b) {
for (ll i = 0; i*i<b; ++i) is_prime_small[i] = true; //对[2,sqrt(b))的初始化全为质数
for (ll i = 0; i<b - a; ++i) is_prime[i] = true; //对下标偏移后的[a,b)进行初始化
for (ll i = 2; i*i<b; ++i) {
if (is_prime_small[i]) {
for (ll j = 2 * i; j*j<b; j += i) is_prime_small[j] = false;
//筛选[2,sqrt(b));
//(a+i-1)/i得到最接近a的i的倍数,最低是i的2倍,然后筛选
for (ll j = max(2LL, (a + i - 1) / i)*i; j<b; j += i) is_prime[j - a] = false;
}
}
for (ll i = 0; i<b - a; ++i) //统计个数
if (is_prime[i]) prime[prime_num++] = i + a;
}
3欧拉筛法
//欧拉筛法,复杂度为o(n)
const int N = 1111111;
int isprime[N], prime[N], num; //isprime为素数筛,prime为素数表,num为表长
void mark_table(int n)
{
num = 0;
memset(isprime, 0, sizeof(isprime));
for (int i = 2; i <= n; i++) {
if (!isprime[i]) prime[num++] = i;
for (int j = 0; j < num; j++)
{
if (prime[j] * i > n) break;
isprime[i*prime[j]] = 1;
if (i%prime[j] == 0) break;
}
}
//for (int i = 0; i < num; i++)
//cout << prime[i] << endl;
}