欧拉筛质数
给点一个正整数 \(n\),请你求出 \(1 \sim n\) 中的质数个数。
欧拉筛法:
- 给点一个正整数 \(n\);
- 先创建两个数组:\(pm[N]\)、\(dt[N]\),分别代表质数数组,和用于筛数的数组;
- 用指针 \(i\) 从 2 开始向右遍历;
- 如果 \(dt[i] == 0\) 就代表 \(i\) 是质数
- 先将 \(i\) 装进 \(pm[N]\) 的尾部;
- 不管 \(i\) 是不是质数,都要用 \(j\) 从 \(pm[N]\) 的头部开始向右遍历,不断的筛去 \(dt[pm[j] * i] = 1\)
- 当然若 \(pm[j] * i > n\) 就没有筛的必要了,直接退出循环。
- 筛去 \(dt[pm[j] * i] = 1\) 了之后,如果 \(i \bmod pm[j] == 0\) 也要退出循环。
由于每个数只被筛一次,所以「时间复杂度」是:\(O(n)\)。
代码参考:
const int N = int (1e7 + 10);
int pm[N], dt[N], cnt;
void get_p(int n)
{
if (n <= 1) return;
for (int i = 2; i <= n; i ++)
{
if (!dt[i]) pm[cnt ++] = i;
for (int j = 0; pm[j] <= n / i; j ++)
{
dt[pm[j] * i] = 1;
if (!(i % pm[j])) break;
}
}
}
868.筛质数
给点一个正整数 \(n\),请你求出 \(1 \sim n\) 中的质数个数。
#include <bits/stdc++.h>
using namespace std;
int debuggersum = 0;
// 即使是不成熟的尝试,
const int N = int (1e7 + 10);
int pm[N], dt[N], cnt;
void get_p(int n)
{
if (n <= 1) return;
for (int i = 2; i <= n; i ++)
{
if (!dt[i]) pm[cnt ++] = i;
for (int j = 0; pm[j] <= n / i; j ++)
{
dt[pm[j] * i] = 1;
if (!(i % pm[j])) break;
}
}
}
void solve(void)
{
int n; scanf ("%d", &n);
get_p(n); printf ("%d\n", cnt);
}
// 也胜于胎死腹中的策略。
int main(void)
{
ifstream fi; ofstream fo;
fi.open("./lrq.in"); fo.open("./lrq.out");
if (fi.is_open() && fo.is_open())
{
fo << "start running ..." << endl; fo.close(); fi.close();
for (long long i = 1; i <= 4e8 + 2e7; i++);
FILE *fin = freopen("./lrq.in", "r", stdin);
FILE *fout = freopen("./lrq.out", "w", stdout);
solve(); fclose(fin); fclose(fout);
}
else solve();
return 0;
}