素数筛法(素数筛 + 线性筛)
求素数的方法在现阶段可以总结为三种
暴力枚举法
这种方法最为简单但效率太低,经过优化时间复杂度最低是O(n*sqrt(n))
代码演示
输入一个n,输出n以内所有素数
#include<stdio.h>
int prime(int n) {
int flag ;
for(int i = 2; i < n; i++) {
flag = 0;
for(int j = 2; j * j <= i; j++) {
if(i % j == 0) {
flag = 1;
}
}
if(flag == 0) {
if(i != 2){
printf(" ");
}优化
printf("%d", i);
}
}
}
int main() {
int n;
scanf("%d", &n);
prime(n);
}
素数筛法
素数筛法原理:2是素数,那么2的所有倍数都是合数,把2所有倍数都标记出来,以此类推,3也是素数,我们也可以把3的所有倍数都标记起来,最后我们可以把所有合数标记起来,素数没有被标记。素数筛的时间复杂度O(nloglogn)比暴力枚举更加有效率,但我们可以看出6这个数字被标记了两次(被2标记了一次又被3标记了一次)所以这种算法还是有缺陷的。
代码演示
输入一个n,输出n( 2<n<2000000)以内所有素数。
#include<stdio.h>
#define max_n 2000000
int pri[max_n + 5] = {0};
int prime(int n) {
for(int i = 2; i < n; i++) {
if(pri[i] == 0){
pri[++pri[0]] = i; /*当做计数器记录素数个数,并且将素数按顺序放到数组中 pri[++pri[0]] = i;相当于先执行++pri[0]再执行pri[pri[0]] = i */
for(int j = 2; j * i < n; j++) {
pri[i * j] = 1;
}
/* for(int j = i * i; j < n; j += i) { 也可以写成这样但这时j要改成long long 类型
pri[j] = 1;
}*/
}
}
}
int main() {
int n;
scanf("%d", &n);
prime(n);
for(int i = 1; i <= pri[0]; i++) {
if(i != 1)printf(" ");
printf("%d", pri[i]);
}
}
线性筛
代码演示
#include<stdio.h>
#define max_n 2000000
int pri[max_n + 5] = {0};
int prime(int n) {
for(int i = 2; i < n; i++) {
if(pri[i] == 0) pri[++pri[0]] = i;
for(int j = 1; j <= pri[0]; j++) {
if(i * pri[j] >= n) break;
pri[i * pri[j]] = 1;
if(i % pri[j] == 0) break;
}
}
}
int main() {
int n;
scanf("%d", &n);
prime(n);
for(int i = 1;i <= pri[0]; i++) {
if(i != 1) printf(" ");
printf("%d", pri[i]);
}
}
有问题可以提哦( ⊙ o ⊙ )!交流学习共同进步鸭鸭鸭二丫