欧拉筛(求质数)
Posted laplus
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了欧拉筛(求质数)相关的知识,希望对你有一定的参考价值。
先上代码:
#include<stdio.h> #include<iostream> #include<string.h> #include<time.h> using namespace std; int prime[10000001];//存素数 bool vis[10000001];//保证不做素数的倍数 int main() { int n, cnt = 0; scanf("%d", &n); clock_t start = clock(); memset(vis, false, sizeof(vis));//初始化 memset(prime, 0, sizeof(prime)); for(int i = 2; i <= n; i++) { if(!vis[i]) { prime[cnt++] = i; for(int j=1;j*i<=n;j++) { vis[j*i]=true; } } } clock_t ends = clock(); cout <<"Running Time : "<<(double)(ends - start)/ CLOCKS_PER_SEC << endl; printf("%d\n", cnt); return 0; }
这并不是完整的欧拉筛,上面的代码从2开始把素数的倍数全部标记为非质数,计算一千万以内的质数个数只需要0.23s
完整欧拉筛代码:
#include<stdio.h> #include<string.h> #include<time.h> #include<iostream> using namespace std; int prime[10000001]; bool vis[10000001]; int main() { int n, cnt = 0; scanf("%d", &n); clock_t start = clock(); memset(vis, false, sizeof(vis)); memset(prime, 0, sizeof(prime)); for(int i = 2; i <= n; i++) { if(!vis[i]) prime[cnt++] = i; for(int j = 0; j<cnt && i*prime[j]<=n; j++) { vis[i*prime[j]] = true; if(i % prime[j] == 0) break; } } clock_t ends = clock(); cout <<"Running Time : "<<(double)(ends - start)/ CLOCKS_PER_SEC << endl; printf("%d\n", cnt); return 0; }
计算一千万以内的质数个数只需要0.12s
先讲讲为什么可以这样算质数吧
首先,先将所有的数标记为质数,然后从2开始,因为2是质数所以它的倍数肯定不是质数,然后3同理,4已经被标记为非质数了跳过,5质数,6也被标记为非质数了跳过.....
然后讲一讲为什么第一个会比第二个快
为什么会这样了?
首先,第一个代码标记2的倍数是标记过1次6,而标记3的倍数时有标记了一次6,所以重复标记花费了时间
而第二个代码,因为这句代码而没有进行重复标记:
for(int j = 0; j<cnt && i*prime[j]<=n; j++)
{
vis[i*prime[j]] = true;
if(i % prime[j] == 0) break;//重点
}
当 i % prime[j] == 0,相当于i=k*prime[j],所以i*preime[i+1]=k*prime[j]*preime[i+1],是质数的倍数,而后面会对他进行标记,所以这次就跳过,终止循环.
第一个代码也可以这样写:
#include<stdio.h> #include<iostream> #include<string.h> #include<time.h> using namespace std; int prime[10000001];//存素数 bool vis[10000001];//保证不做素数的倍数 int main() { int n, cnt = 0; scanf("%d", &n); clock_t start = clock(); memset(vis, false, sizeof(vis));//初始化 memset(prime, 0, sizeof(prime)); for(int i = 2; i <= n; i++) { if(!vis[i]) { prime[cnt++] = i; } for(int j = 0; j<cnt && i*prime[j]<=n; j++) { vis[i*prime[j]] = true; } } clock_t ends = clock(); cout <<"Running Time : "<<(double)(ends - start)/ CLOCKS_PER_SEC << endl; printf("%d\n", cnt); return 0; }
以上是关于欧拉筛(求质数)的主要内容,如果未能解决你的问题,请参考以下文章