素数判断-----埃氏筛法&欧拉筛法

埃氏筛法

/*
    |埃式筛法|
    |快速筛选素数|
    |15-7-26|
*/
#include <iostream>
#include <cstdio>
using namespace std;
const int SIZE = 1e7;

int prime[SIZE];            // 第i个素数
bool is_prime[SIZE];    //true表示i是素数

int slove(int n)
{
    int p = 0;
    for(int i = 0; i <= n; i++)
        is_prime[i] = true;             //初始化
    is_prime[0] = is_prime[1] = false;      //0,1不是素数
    for(int i = 2; i <= n; i++)
    {
        if(is_prime[i])                //这里比较巧妙, 我只是意会
        {
            prime[p++] = i;             //计算素数的个数,也记录下了素数
            for(int j = 2 * i; j <= n; j += i)      // 除掉了i的倍数的数字
                is_prime[j] = false;
        }
    }
    return p;
}

int main()
{
    int n;
    while(cin >> n)
    {
        int res = slove(n);
        cout << res << endl;
        for(int i = 0; i < res; i++)
            cout << prime[i] << endl;
    }
}

 

2 3 4 5 6 7 8 9 10 11 12
2 3 - 5 - 7 - 9 - 11 -
2 3 - 5 - 7 - - - 11 -

结合这张表看看,慢慢一次次的都筛选完了..

其中最小的素数是2,将表中所有2的倍数都除去,剩下最小的数是3,不能被更小的数整除,所以是素数.再将表中3的倍数的数除去.以此类推.如果表中最小的数字是m,m就是素数.然后将表中所有m的倍数都除去...然后就可以了= =

话说要是求区间[x,y]内求素数个数的话,只要0~y的素数个数-0~x的素数个数就可以了,然后判断x是否为素数就可以了...

 

 

 

欧拉函数

 

#include<cstdio>
#include<cmath>
using namespace std;
#define m 5800000
#define m1 100000000
int n,len,a[m];
bool vis[m1];
int main()
{
    scanf("%d",&n);
    for(int i = 2;i <= n;i++)
    {
        if(!vis[i])
            a[++len] = i;
        for(int j = 1;(j <= len )&&(i * a[j] <= n);j++)
        {
            vis[a[j] * i] = true;
            if(!(i % a[j]))
                break;
        }
    }
    printf("%d",len);
    return 0;
}

 

 

要说保证某数不被重复判断,关键就在这行代码上。
满足上式时,i是pri[j]的倍数,那么对于后面的pri[k]来说,i * pri[k]就可以被分解为pri[j] * (i / pri[j] *pri[k]),而该数在之前i == pri[j]的时候已经出现过,于是就重复了。直接退出,避免了重复判定。

欧拉筛法固然快,但是也有适用条件,例如求(n, n + 10)中的素数个数的时候,它就明显慢了。由于必须从1开始,所以欧拉筛法的用处在于直接打表而不是求某一段区间。对于这种问题,朴素法未尝不可。

欧拉筛法的原理分析至此结束。

 

 

 

------=====-----=====-----====-----======-------=========================================================

 

埃氏筛法:

从2开始把素数的倍数都给标记掉,复杂度为 O(nlog(logn)) 。

 

欧拉筛法:

把2压到栈/队列中,外面的数可以被栈/队列中的数整除的话,丢掉,不能的话,压入栈/队列中。

 

以6为例:

埃氏筛法会遍历到他很多遍

欧拉筛法只会遍历一遍

posted @ 2019-01-29 20:49  darrrr  阅读(862)  评论(0编辑  收藏  举报