一、判断素数
素数:除1和他本身外,不能被其他数整除的数;
素数筛: 首先,给你一个区间的正整数,让你求在这段区间内有哪些素数?
这里,我们就可以用“筛选的方法”筛去不是素数的正整数(也就是合数)剩下的就是素数了,但不同的筛法效率也是不一样的。
二、筛选方法
1.暴力求法
bool IsPrime(int x){
for(int i = 2; i < sqrt(x); i ++){
if(x % i == 0) return false;
}
return true;
}
2.埃氏筛
又称为埃拉托斯特尼筛法,是一种比较古老的筛法,我们直接来看它的筛法原理。其时间复杂度为:
1.准备一个判断是否素数的数组,
> bool isPrime[20000];
2.初始化:假设 2 - n都是素数。(1不是,我们先排除)
for(int i=2;i<=n;++i)
isPrime[i] = true;
挨氏筛的完整代码如下:
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
bool isprime[N];
void Eratosthens(int maxn){
memset(isprime, true, sizeof(isprime));//注意:memset()函数是对字节赋值
isprime[0] = isprime[1] = false;
for(int i = 2; i < maxn; i ++){
if(isprime[i]){
for(int j = 2*i; j <=maxn; j = j + i){
isprime[j] = false;
}
}
}
return;
}
由于每个数可能有很多除了1和它本身之外的因数,因此在挨氏筛中,每个合数可能重复多次被筛去,要使时间复杂度为线性,我们想要使每个数只被筛去一次。
3.快速线性筛(欧拉筛)
最小质因数:最小质因数是指将一个合数进行分解质因数,把它写成一些质因数相乘的形式,这其中最小的因数就叫做最小质因数。
原理:利用每个数的最小质因子来筛素数。每个数的最小素数因子只有一个,这就使每个合数都只可能被筛去一次。时间复杂度为线性。
i用来控制倍数,红色部分进行break,灰色部分不执行如43=12,4可以分解为22所以用6 * 2 =12 进行筛
完整代码如下
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
bool isprime[N];
int primes[N], pn;
void FastSieve(int maxn)
{ //筛区间0 ~ maxn之间的素数
memset(isprime, true, sizeof(isprime));
isprime[0] = isprime[1] = false;
pn = 0;
for (int i = 2; i <= maxn; ++i)
{
if (isprime[i])
primes[pn++] = i;
for (int j = 0; j < pn && i * primes[j] <= maxn; j++)
{
isprime[i * primes[j]] = false;
if (i % primes[j] == 0)
break;
}
}
return;
}
例题:
用筛法求之N内的素数。
输入 N
输出 0~N的素数
样例输入 100
样例输出 略
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
bool isprime[N];
int primes[N], pn;
void FastSieve(int maxn)
{ //筛区间0 ~ maxn之间的素数
memset(isprime, true, sizeof(isprime));
isprime[0] = isprime[1] = false;
pn = 0;
for (int i = 2; i <= maxn; ++i)
{
if (isprime[i])
primes[pn++] = i;
for (int j = 0; j < pn && i * primes[j] <= maxn; j++) //注意取值范围为≤
{
isprime[i * primes[j]] = false;
if (i % primes[j] == 0)
break;
}
}
return;
}
int main()
{
int n;
cin >> n;
FastSieve(n);
for(int i = 0; i < pn; i ++){
cout << primes[i] << endl;
}
// for (int i = 2; i <= n; i++)
// {
// if (isprime[i])
// cout << i << endl;
// }
}