//筛法求素数 #include<cstdio> #include<cmath> #define N 10000001 bool prime[N]; int main() { int i, j; for(i=2; i<N; i++) if(i%2) prime[i]=true; else prime[i]=false; for(i=3; i<=sqrt(N*1.0); i++) { if(prime[i]) for(j=i+i; j<N; j+=i) prime[j]=false; } for(i=2; i<403; i++)//由于输出将占用太多io时间,所以只输出2-100内的素数。可以把100改为N if( prime[i] )printf("%d ",i); return 0; } //改进后的筛法,更快 另外,对于这样的筛法,还可以进一步优化,就是bool型数组里面只存奇数不存偶数。如定义prime[N],则0表示 3,1表示5,2表示7,3表示9...。如果prime[0]为true,则表示3时素数。prime[3]为false意味着9是合数。 这样的优化不是简单的减少了一半的循环时间,比如按照原始的筛法,数组的下标就对应数。则在计算30以内素 数的时候3个步骤加起来走了15个单位时间。但是用这样的优化则是这样: 则由于只存3 5 7 9 11 13 15 17 19 21 23 25 27 29,只需要14个单元 第 1 步 把14个单元赋为true (每个单元代表的数是2*i+3,如第0单元代表3,第1单元代表5...) 第 2 步开始: i=0; 由于prime[0]=true, 把 [3], [6], [9], [12]标为false. i=1; 由于prime[1]=true, 把 [6], [11]标为false i=2 2*i+3>sqrt(30)算法结束。 这样优化以后总共只走6个单位时间。 当n相当大以后这样的优化效果就更加明显,效率绝对不仅仅是翻倍。 出了这样的优化以外,另外在每一次用当前已得出的素数筛选后面的数的时候可以一步跳到已经被判定不是素数的 #include<cstdio> #include<cmath> #include <string> #define N 10000001 bool prime[N/2+1]; int main() { memset(prime,true,sizeof(prime)); for (int i=0;i*2+3<=sqrt(N*1.0);i++) { if (prime[i]) for (int j=i*6+9;j<N;j+=i*4+6) prime[(j-3)/2]=false; //这里如果加一个判断已为false跳过重复计算就更快了 } for (int i=0;i<200;i++) if (prime[i]) printf("%d ",i*2+3); return 0; } //建立素数表 #include <iostream> using namespace std; bool IsPrime2( int n ) { if ( n < 2 ) { // 小于2的数即不是合数也不是素数 return false; } static int aPrimeList[] = { // 素数表 1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 113, 193, 241, 257, 337, 353, 401, 433, 449, 577, 593, 641, 673, 769, 881, 929, 977, 1009, 1153, 1201, 1217, 1249, 1297, 1361, 1409, 1489, 1553, 1601, 1697, 1777, 1873, 1889, 2017, 2081, 2113, 2129, 2161, 2273, 2417, 2593, 2609, 2657, 2689, 2753, 2801, 2833, 2897, 3041, 3089, 3121, 3137, 3169, 3217, 3313, 3329, 3361, 3457, 3617, 3697, 3761, 3793, 3889, 4001, 4049, 4129, 4177, 4241, 4273, 4289, 4337, 4481, 4513, 4561, 4657, 4673, 4721, 4801, 4817, 4993, 5009, 5153, 5233, 5281, 5297, 5393, 5441, 5521, 5569, 5857, 5953, 6113, 6257, 6337, 6353, 6449, 6481, 6529, 6577, 6673, 6689, 6737, 6833, 6961, 6977, 7057, 7121, 7297, 7393, 7457, 7489, 7537, 7649, 7681, 7793, 7841, 7873, 7937, 8017, 8081, 8161, 8209, 8273, 8353, 8369, 8513, 8609, 8641, 8689, 8737, 8753, 8849, 8929, 9041, 9137, 9281, 9377, 9473, 9521, 9601, 9649, 9697, 9857 }; const int nListNum = sizeof(aPrimeList) / sizeof(unsigned); for ( int i = 1; i < nListNum; ++i ) { // 和比它小的所有的数相除,如果都除不尽,证明素数 if ( n / 2 + 1 < aPrimeList[i] ) { // 一定是素数了 return true; } if ( 0 == n % aPrimeList[i] ) { // 除尽了,合数 return false; } } for ( int i = aPrimeList[nListNum - 1]; i < n / 2 + 1; i++ ) { // 真不幸,遇到了这么大的素数 if ( 0 == n % i ) { // 除尽了,合数 return false; } } return true; } //根据费马小定理,有一定概率 #include <iostream> #include <ctime> using namespace std; int witness(int a,int i,int n) { if (i==0) return 1; int x=witness(a,i/2,n); if (x==0) return 0; int y=(x*x) % n; if (y==0 && x!=1 && x!=n-1) return 0; if (i % 2 != 0) y=(a*y) % n; return y; } bool isprime(const int & n) { for (int i=0;i<5;i++) { srand((unsigned) time(NULL)); if (witness ((rand()%(n-1))+2,n-1,n) != 1) return false; } return true; } int main() { int n; cin>>n; cout<<isprime(n); system("pause"); return 0;}