线性筛 埃式筛 欧拉筛
题目:给出一个正整数n,打印出所有从1~n的素数(即质数);
普通解法
#include<iostream> #include<algorithm> #include<cmath> using namespace std; bool isprime(int n) { if (n == 0 || n == 1)return false; for (int i = 2; i <=sqrt(n); i++) if (n%i == 0)return false; return true; } int main() { int n; scanf("%d", &n); for (int i = 0; i <=n; i++) { if (isprime(i))printf(" %d", i); } }
埃拉托斯特尼筛法
算法思路:算法从小到大枚举所有数,对于每一个素数,筛去它的所有倍数,剩下的就都是素数了。
#include<iostream> #include<algorithm> #include<cmath> using namespace std; bool p[1000];//是否被筛去,默认为false int prime[1000], cnt = 0; void findprime(int n) { for (int i = 2; i <= n; i++) { if (!p[i])//没有被筛去的话 { prime[cnt++] = i;//素数加1, for (int j = i + i; j <= n; j += i)//int j = i + i:从2开始,但是不能筛去2,所以从4开始 p[j] = true;//筛去素数的倍数 } } } int main() { int n; scanf("%d", &n); findprime(n); for (int i = 0; i <cnt; i++) { printf(" %d", prime[i]); } }
欧拉筛
算法思路:在埃氏筛法的基础上,让每个合数只被它的最小质因子筛选一次,以达到不重复的目的。
#include<iostream> #include<algorithm> #include<cmath> using namespace std; bool p[1000]; int prime[1000], cnt = 0; void findprime(int n) { for (int i = 2; i <= n; i++) { if (!p[i])//未筛去的话 prime[cnt++] = i;//素数记录 for (int j = 0; j < cnt; j++) { if (i*prime[j] <= n)//用i作为倍数,筛去prime[j]中的素数的倍数 { p[i*prime[j]] = true; if (i%prime[j] == 0)break; //例子:i = 8 ,j = 1,prime[j] = 2,如果不跳出循环,prime[j+1] = 3,8 * 3 = 2 * 4 * 3 = 2 * 12,在i = 12时会计算。 } } } } int main() { int n; scanf("%d", &n); findprime(n); for (int i = 0; i <cnt; i++) { printf(" %d", prime[i]); } }