欧拉筛算法可以在O(N)时间内对1~N范围内的数字进行判断并标记其是否为素数.
基于这样的思想:
- 一个质数的x倍(x>1且为整数)一定不是质数.
- 反过来,如果一个数不是任何一个质数的x倍(x>1且为整数),那么其一定是质数.
然而要保证线性复杂度,需要在实现上进行很多细节处理.具体的解释看别人写的博客来的快.
实现保证每当一个合数 i * s[j] 被筛除时,s[j]为该合数的最小质因数,i为该合数的最大非自身因数.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <algorithm> #include <cstdio> #include <cstring> #include <iostream> #include <vector> using namespace std; bool isPrime[100000010]; // 本题的空间限制为512MB, 时间限制为2s int n, q; vector<int> s; // 执行此函数后,可以通过isPrime[x]查询x是否为素数,也可以查询第x个质数s[x] // 如果不需要后一项功能,可以把s的声明放到这个函数里 void init(int n) { fill(isPrime, isPrime + 100000010, 1); isPrime[1] = isPrime[0] = 0; for (int i = 2; i <= n; i++) { if (isPrime[i]) s.push_back(i); for (int j = 0; j < s.size() && i * s[j] <= n; j++) { isPrime[i * s[j]] = 0; if (i % s[j] == 0) break; } } } int main() { scanf("%d%d", &n, &q); init(n); while (q--) { int k; scanf("%d", &k); printf("%d ", s[k - 1]); // 第 "k" 小 } return 0; } 欧拉筛 P3383