素数,又称质数,即除了 1 和 本身 再没有其他因子的整数;我们可以通过筛法来求素数:
普通筛法
for (int i = 2; i <= n; ++i) {
if (s[i] == 0) s[p++] = i;
for (int k=i*i; k<n; k+=i)
prime[k]=false;
}
相对于普通的筛法,线性筛只是在这里稍加修正:
for (int i = 2; i <= n; ++i) {
if (s[i] == 0) s[p++] = i;
普通筛法的这一段是遍历 j , 使得重复筛了许多数,因此下面的代码改进,将筛的目标缩小了,不必遍历j,只需要对已保存素数的i倍的数进行即可。因为 i 不断增大,所以和最小质因子和的乘积不会重复,进一步简化了复杂度达到O(n)
//
for (int j = 1; j < p && i * s[j] <= n; ++j) {
s[i * s[j]] = 1;
if (i % s[j] == 0) break;
/
}
}
线性筛法
#include <iostream>
using namespace std;
int s[1000000];
int main()
{
long n;
while (cin >> n)
{
long p = 1;
memset(s, 0, sizeof(s));
for (int i = 2; i <= n; ++i) { //2--n
if (s[i] == 0) s[p++] = i; // 添加素数
for (int j = 1; j < p && i * s[j] <= n; ++j) {
s[i * s[j]] = 1; //最小质因子对每个合数只筛一次
if (i % s[j] == 0) break;
}
}
for (int i = 1; i < p; ++i) {
cout << s[i] << " ";
}
cout << '\n';
}
return 0;
}
对这个线性筛法,我们还可以剪剪枝叶,能直接判断的:除2外的所有偶数,因此可以只看奇数,又能优化点点了,剩下的留给自己试试0.0!