入门级的标准解法如下:
#include <iostream> #include <vector> using namespace std; vector<int> ivec; bool isPrime(int number) { bool result = true; for (int i = 2; i < number; i++) { if (number % i == 0) { result = false; break; } } return result; } void generateNPrime(int N) { int count = N; int number = 2; while (count) { if (isPrime(number) == true) { count--; ivec.push_back(number); } number++; } } void main() { generateNPrime(100); copy(ivec.begin(), ivec.end(), ostream_iterator<int>(cout, " ")); }
bool isPrime(int number) { bool result = true; for (int i = 2; i <= number >> 1; i++) { if (number % i == 0) { result = false; break; } } return result; }
bool isPrime(int number) { bool result = true; for (int i = 2; i <= sqrt((double)(number)); i++) { if (number % i == 0) { result = false; break; } } return result; }
比起开方运算,更建议使用平方来求解,平方的效率更高,而且开方存在精度问题
bool isPrime(int number) { bool result = true; for (int i = 2; i * i <= number; i++) { if (number % i == 0) { result = false; break; } } return result; }
先来看一下100以内的素数:
2 3 5 7 11 13 17...
我们可以看到素数的规律在5之后是2、4、2、4这样间隔着出现,但是会一直这样间隔出现吗,答案是否定的,但是非这样的间隔必然不是素数
因为6n, 6n+1, 6n+2, 6n+3, 6n+4, 6n+5,只有6n+1和6n+5需要检测是否为素数
所以可以做一定程度上的筛选:
void generateNPrime(int N) { int count = N; int number = 5; ivec.push_back(2); ivec.push_back(3); ivec.push_back(5); count -= 3; int gap = 2; while (count) { number += gap; gap = 6 - gap; if (isPrime(number) == true) { count--; ivec.push_back(number); } } }
时间复杂度为O(N)的素数筛选法!!!
原理如下:
1. 首选选取一个素数n
2. 选取素数m,m从n开始,依次选取下一个素数,跳出条件是n * m <= N
3. 选取素数p,p从m * n开始选取,每次*素数n,跳出条件是p * n <= N
删除
例如20以内的素数
2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,16, 17, 18, 19, 20
选取素数n,n = 2; 那么m = 2, p = 4;
开始remove p,循环下来,4, 8, 16全部被删除
m选取下一个数,选取3
remove p,循环下来,6, 12
m选取下一个数,选取5
remove p,循环下来,删除10, 20
m选取下一个数,选取7,删除14
m选取下一个数,选取9,删除18
第一重循环跳出,经过本轮筛选,剩下的数字为:
2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,16, 17, 18, 19, 20
重复上面的逻辑,再经过一轮筛选,不难得出剩下的数字为:
2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,15,16, 17, 18, 19, 20
两轮筛选后,循环跳出~
#include <iostream> using namespace std; #define MAXSIZE 1000 #define NEXT(x) x = next[x] #define PREVIOUS(x) x = previous[x - 1] #define REMOVE(x) { next[PREVIOUS(x)] = next[x]; \ previous[next[x]] = previous[x]; } #define INITIAL(n) { unsigned long i; \ for (int i = 2; i <= n; i++) \ previous[i] = i - 1, next[i] = i + 1; \ previous[2] = next[n] = 0; \ } void main() { unsigned long previous[MAXSIZE + 1]; unsigned long next[MAXSIZE + 1]; unsigned long prime, fact, i, mult; unsigned long n; unsigned long count = 0; printf("\nLinear Sieve Program"); printf("\n===================="); printf("\n\nPrime Numbers between 2 to --> "); scanf("%d", &n); INITIAL(n); for (prime = 2; prime * prime <= n; prime = next[prime]) for (fact = prime; prime * fact <= n; fact = next[fact]) for (mult = prime * fact; mult <= n; mult *= prime) { if (fact == 9) cout << "mult = " << mult << endl; next[previous[mult]] = next[mult]; previous[next[mult]] = previous[mult]; } for (int i = 2; i != 0; i = next[i]) { if (count % 8 == 0) printf("\n"); printf("%6ld", i); count++; } printf("\n\nThere are %ld Prime Numbers in Total", count); }