1. 使用筛选法求素数的思想是:使用一个bool isPrime[N]来存储一个数是不是素数的标志位。
首先偶数不是素数(2除外),将2的倍数isPrime全部设置为false。
i从3开始遍历,如果i为素数,则将i的倍数isPrime全部设置成false。这样就筛选掉了好多不是素数的数。
从0遍历isPrime[i]数组,如果值为true,则说明i为素数,否则i不是素数。
2. 代码如下:
View Code
1 #include <iostream> 2 #include <cassert> 3 #include <cmath> 4 using namespace std; 5 6 #define N 10000001 7 bool isPrime[N]; 8 9 bool Prime(int n) 10 { 11 if (n<2) 12 { 13 return false; 14 } 15 if (n==2) 16 { 17 return true; 18 } 19 int upper=sqrt(static_cast<double>(n)); 20 for (int i=2;i<=upper;i++) 21 { 22 if (n%i==0) 23 { 24 return false; 25 } 26 } 27 return true; 28 } 29 int main() 30 { 31 isPrime[0]=isPrime[1]=false; 32 isPrime[2]=true; 33 int i=2; 34 for (int i=3;i<N;i++) 35 { 36 if ((i&(0x01)) ==0) //用位运算代替i%2==0 37 { 38 isPrime[i]=false; 39 } 40 else 41 { 42 isPrime[i]=true; 43 } 44 } 45 int upper=sqrt(static_cast<double>(N)); 46 for(int i=3;i<upper;i+=2) 47 { 48 if (isPrime[i] && Prime(i)) 49 { 50 for (int j=i+i;j<N;j+=i) 51 { 52 isPrime[j]=false; 53 } 54 } 55 } 56 int count=0; 57 for (int i=0;i<N;i++) 58 { 59 if (isPrime[i]) 60 { 61 //cout<<i<<" "; 62 count++; 63 } 64 } 65 cout<<count<<endl; 66 67 //最原始的求素数方法,速度很慢 68 //int count=0; 69 //for (int i=2;i<N;i++) 70 //{ 71 // if (Prime(i)) 72 // { 73 // count++; 74 // } 75 //} 76 //cout<<count<<endl; 77 return 0; 78 }
3. 代码可以做如下优化:
1. isPrime数组大小可减少为原来的一半,只存储素数的标志位,不存储偶数的标志位。毕竟偶数都不是质数。
2. 如果判断一个数是不是素数,可以维护一个很大的素数表,即将一定范围内的素数首先都求出来,存储在数组内,为了节省内存可以使用位图存储。
4. 参考文章: