P3383 【模板】线性筛素数
线性筛法求质数
做法
-
用数组 \(v\) 来存储每个数的最小质因子
-
枚举2~n之间的数
-
若\(v[i] == i\) 则该数为质数,将其保存
-
穷举2~\(v[i]\)的质数 \(p\) (不包含\(v[i]\)),则\(v[i*q]\) = \(q\)
- 因为 \(p\) 小于\(v[i]\), 所以合数 \(v[i*p]\) 的最小质因子是 \(p\)
推论
-
从头往后挨个枚举,只要满足\(v[i] = i\),就加入prime[]
-
并把对应的\(v[i*q](q\le v[i])\)更新,从而达到类似DP的动态类取数问题
-
\(prime\) 数组存储 \(n\) 中的质数,这样就可以打印出每一个质数啦
-
时间复杂度 \(O(n)\)
Code
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
const int manx=1e8+10;
const int mamx = 1e6 + 11;
const int B = 1e6 + 11;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
inline int read() {
char c = getchar(); int x = 0, f = 1;
for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1;
for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
return x * f;
}
int v[manx],prime[manx],m;
void primes(int n){
memset(v,0,sizeof(v));
m = 0;
for(int i = 2;i <= n; i++){
if(v[i] == 0){
v[i] = i;
prime[++m] = i;
}
for(int j = 1;j <= m; j++){
if(prime[j] > v[i] || prime[j] >n/i)break;//i有比prime[j]更小的因子,或者超出n的范围,则跳出循环
v[i*prime[j]] = prime[j];
}
}
//for(int i = 1;i <= m ;i++)cout<<prime[i]<<endl;
sort(prime + 1,prime + 1 + m);
}
int main(){
int n = read(),q = read();
primes(n);
for(int i = 1; i <= q; i++)
{
int x = read();
//cout<<prime[x]<<endl;
}
return 0;
}

浙公网安备 33010602011771号