·一. 暴力遍历取模。(不过多解释)
微改良的是可以从2遍历到根号n。
// 用于求单个质数。
二. 埃氏筛
从二到n枚举,将枚举的每个数的倍数打上是质数的标记。把是质数的数记录到数组中。
用于求一个区间内的质素。
代码如下
const int N = 1e5 + 10;
int prime[N];
bool is_prime[N];
int p = 0;
void find(int n)
{
for(int i = 0; i <= n;i ++) is_prime[i] = true;
is_prime[0] = is_prime[1] = false;
for(int i = 2;i <= n;i ++){
if(!is_prime[i]){
prime[p ++] = i;
for(int j = i;j < n / i;j ++) is_prime[j * i] = false;//优化一下j从开始遍历
}
}
}
此方法会遇到一个非质数多次被标记的情况不是最优解。
三.线性筛
此方法可看作上一方法的上位代替解决了重复标记的问题。
代码如下
const int N = 1e5 + 10;
int prime[N], p = 0;
bool is_prime[N];
void find(int n){
for(int i = 2;i <= n;i ++){
if(!is_prime[i])prime[p ++] = i;
for(int j = 0;j < p&&prime[j]*i <= n;j ++){
is_prime[i * prime[j] = 1;
if(i%prime[j] == 0) break;//可以如此理解所有i先将其两倍筛去,接着筛去三倍,5倍,7倍......;
反过来理解将所有数能除2二的就筛去并break,否则能除3的晒去依次类推。
}