素数筛合集
原始、暴力,时间复杂度O(n*sqrt(n))
bool isprime(int n){
int i;
for (i = 2; i <= sqrt(n); i++)
if (n % i == 0)
return false;
return true;
}
一般筛法:时间复杂度O(nloglogn)
const int maxn = 100;
bool number[maxn + 5];
void isprime() {
int i, j;
memset(number, true, sizeof(number));
for (i = 2; i <= maxn; i++) {
if (number[i] == true) {
for (j = 2; j * i <= maxn; j++)
number[i * j] = false;
}
}
}
小改进,省去了j到i平方的这一部分
const int maxn = 100;
bool number[maxn + 5];
void isprime() {
int i, j;
memset(number, true, sizeof(number));
for (i = 2; i <= maxn; i++) {
if (number[i] == true) {
for (j = i*i; j <= maxn; j+=i)
number[j] = false;
}
}
}
终极超级无敌欧拉筛法,时间复杂度为O(n)
思想:每个合数只被它的最小质因子筛选一次,以达到不重复的目的
prime[]数组中的素数是递增的, 当i能被prime[j]整除,那么i* prime[j + 1]这个合数肯定被prime[j]乘以某个数筛掉。
因为i中含有prime[j], prime[j]比prime[j + 1]小,即i = k * prime[j],那么i * prime[j + 1] = (k * prime[j]) * prime
[j + 1] = k’ * prime[j],
接下去的素数同理。所以不用筛下去了。因此,在满足i % prime[j] == 0这个条件之前以及第一次
满足改条件时, prime[j]必定是prime[j] * i 的最小因子。
bool number[maxn + 5];//记录下标是不是素数
void isprime() {
int prime[maxn + 5];//记录素数
int i, j, c = 0;
memset(number, true, sizeof(number));
for (i = 2; i <= maxn; i++) {
if (number[i])
prime[c++] = i;
for (j = 0; j < c && prime[j] * i <= maxn; j++) {
/*超出pri数组的范围/超出数据范围,1条件不必有*/
number[prime[j] * i] = false;
if (i % prime[j] == 0) //见题解
break;
}
}
}