线性筛
首先说声抱歉,最近一直忙着调剂,没有及时更新。
今天说下素数筛的进化版——线性筛(很方便的)
上次我们说到,素数筛的缺点就是一个合数有可能会重复的去判断,如果能一次性的判断,就成为线性的的时间了。大家发现:每个合数必有一个最小素因子。每个合数仅被它的最小素因子筛去正好一次。用mark[ ]做为标记数组,用pri[ ]保存所有素数,mark[i * pri[j]] = 1这就语句,就是精华所在,即每个合数仅被它的最小素因子筛去正好一次,执行这语句时i % pri[j] == 0,pri[j]一定是pri[j] * i 的最小因子。
下面代码献上(以求100000内的素数和为例)
注:我把mark[]和pri[]定义成全局变量,是为了方便,实际中按照个人喜好便可
#include<iostream>
using namespace std;
#define MAX 100000
int pri[MAX] = {0};
int mark[MAX] = {1, 1, 0};
int index = 0;
void prime(){ //线性筛
int i, j;
for(i = 2; i < MAX; i++){
if(mark[i] == 0){
pri[index++] = i;
}
for(j = 0; j < index && pri[j] * i < MAX; j++){
mark[i * pri[j]] = 1; // 个合数仅被它的最小素因子筛去正好一次
if(i % pri[j] == 0){
break;
}
}
}
return ;
}
void putout(){ //输出MAX以内的所有素数
int i;
for(i = 0; i < index; i++){
cout << pri[i] << " ";
}
return ;
}
int sum(){ //求和
int i, pri_sum = 0;
for(i = 0; i < index; i++){
pri_sum += pri[i];
}
return pri_sum;
}
int main(){
prime();
//putout();
cout << MAX <<" 以内素数和为 " << sum() << endl;
return 0;
}