码迷,mamicode.com
首页 > 其他好文 > 详细

欧拉筛(求质数)

时间:2018-05-05 20:36:19      阅读:166      评论:0      收藏:0      [点我收藏+]

标签:mes   没有   c99   千万   isp   完整   include   mem   star   

先上代码:

技术分享图片
#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;
}
View Code

这并不是完整的欧拉筛,上面的代码从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;
}
View Code

计算一千万以内的质数个数只需要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;
}
View Code

 

欧拉筛(求质数)

标签:mes   没有   c99   千万   isp   完整   include   mem   star   

原文地址:https://www.cnblogs.com/swustzww/p/8995766.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!