埃氏筛法

埃氏筛法,理解起来很好理解,就是在1~n这n个连续的数里面开始筛出合数,知道剩下全部为素数,大致流程如下:

第一步:能够确定1不是素数,所以将1筛出,剩下从2开始的数列

第二步:找到2为第一个素数,那么遍历这个数列,将2的倍数筛出,形成一个新的数列

第三步:找到下一个素数 x,此时 x = 3,那么再次遍历这个数列,筛出 x 的倍数,剩下的数再次形成一个新的数列

第四步:重复第三步,直到将所有合数筛出

代码如下:

#include <iostream>
#include <cstring>
#define N 1000005
using namespace std;

int a[N];//存放素数的数组a
int b[N];//数字对应表

main()
{
    int n;
    while( cin >> n )//输入查找上限
    {
        memset( a, 0 ,sizeof(a) );
        memset( b, 1 ,sizeof(b) );//下标对应数字为素数则为1,否则为0,全部初始化为1
        int t = 0;//记录素数个数的变量
        b[0] = 0; b[1] = 0;// 0、1不是素数
        for( int i(0); i <= n; i++ )// 遍历不大于n的所有数
        {
            if ( b[i] )//如果这个数为素数
            {
                a[t++] = i;
                for( int j = 2*i; j <= n; j += i )// 此时i为找到的一个素数,所有 i的倍数都不是素数
                    b[j] = 0;
            }
        }
        for( int i(0); i < t; i++ )
            cout << a[i] <<"\t";
        cout << endl << "小于" << n << "的数中,共有" << t << "个素数" <<endl;
    }
}

运行一下就知道,这个筛数法非常的好用,即使输入1e6也能在很短的时间之内筛完,并且开始输出,但是任然存在一个问题,我可不可以不用一直筛到 n?而是在筛到n之前,且完成了将所有合数筛出后就退出呢?

答案是可以的!根据埃氏筛法的结论,我只需要筛到小于√n的那一个素数就行了,至于为什么就不在赘述,既然有了这个结论,很容易就写出来代码

如下:

#include <iostream>
#include <cstring>
#define N 1000005
using namespace std;

int b[N];//数字对应表

main()
{
    int n;
    while( cin >> n )//输入查找上限
    {
        memset( b, 1 ,sizeof(b) );//下标对应数字为素数则为1,否则为0,全部初始化为1
        b[0] = 0; b[1] = 0;// 0、1不是素数
        for( int i(0); i*i <= n; i++ )// 遍历不大于n的所有数
            if ( b[i] )//如果这个数为素数
                for( int j = 2*i; j <= n; j += i )// 此时i为找到的一个素数,所有 i的倍数都不是素数
                    b[j] = 0;
        for( int i(0); i < n; i++ )
            if(  b[i] )
                cout << i <<"\t";
    }
}

两个代码,很明显前面一个会慢一点,但是我能在筛的同时取出素数,而后一个,应为没有遍历整个数组,所以还需要遍历一下整个b数组才能知道哪些是素数。

时间: 2024-08-08 01:26:20

埃氏筛法的相关文章

分拆素数和 埃氏筛法

分拆素数和 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 2098 Description 把一个偶数拆成两个不同素数的和,有几种拆法呢? Input 输入包含一些正的偶数,其值不会超过10000,个数不会超过500,若遇0,则结束. Output 对应每个偶数,输出其拆成不同素数的个数,每个结果占一行. Sample Input 30

素数的快速筛选(埃氏筛法)

要枚举n以内的素数,可以用埃氏筛法.这是一个与辗转相除法一样古老的算法. 首先,将2到n范围内的所有整数写下来.其中最小的数字2是素数.将表中所有2的倍数都划去.表中剩余的最小数字是3,它不能被更小的数整除,所以是素数.再将表中所有3的倍数全都划去.依次类推,如果表中剩余的最小数字是m时,m就是素数.然后将表中所有m的倍数全部划去.像这样反复操作,就能依次枚举n以内的素数. int prime[maxn];//第i个素数 bool is_prime[maxn];//is_prime[i]为tru

埃氏筛法之素数

原理: 首先将2~n个数记录下来,2作为最小素数,所以2的倍数不是素数,从记录中划去,扫一遍之后,将3作为最小素数,3的倍数划去,如此下去,求出所有素数.如表格所示: 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 2 3 - 5 - 7 - 9 - 11 - 13 - 15 - 17 - 19 - 2 3 - 5 - 7 - - - 11 - 13 - - - 17 - 19 - 代码: 判断是否是素数: bool is_prime(int n

埃氏筛法的一般写法

问题: 求[L, R]之间的素数表 解法: 先用埃氏筛法求出[1...sqrt(R)]上的素数表 再在[L, R]上用埃氏筛法求素数 const int N(1e5); bool isprime[N]; int prime[N]; void init(){ memset(isprime, -1, sizeof(isprime)); isprime[0]=isprime[1]=0; int np=0; for(int i=0; i<N; i++){ if(isprime[i]){ prime[np

埃氏筛法(素数筛)

埃式筛法:给定一个正整数n(n<=10^6),问n以内有多少个素数? 做法:做法其实很简单,首先将2到n范围内的整数写下来,其中2是最小的素数.将表中所有的2的倍数划去,表中剩下的最小的数字就是3,他不能被更小的数整除,所以3是素数.再将表中所有的3的倍数划去……以此类推,如果表中剩余的最小的数是m,那么m就是素数.然后将表中所有m的倍数划去,像这样反复操作,就能依次枚举n以内的素数,这样的时间复杂度是O(nloglogn). 题解:如果要是按照一个一个判断是否是素数然后把ans+1,时间复杂度

素数的计算-埃氏筛法(区间素数利器)

素数,各种素数,各种题总是遇到素数. 下面我们来说一下求素数的一种比较有效的算法. 就是筛法.因为这个要求得1-n区间的素数只需要O(nloglogn)的时间复杂度. 下面来说一下它的思路. 思路:现在又1-n的数字,素数嘛就是除了1和本身之外没有其他的约数,所以有约数的都不是素数. 我们从2开始往后遍历,是2的倍数的都不是素数,所以我们把他们划掉 然后现在从2往后就是3了 因为3的前面没有能整除3的,所以3是素数,然后3的倍数全都不是素数,我们接着划掉. 然后就是5了,因为4是2的倍数不是素数

DP+埃氏筛法 Codeforces Round #304 (Div. 2) D. Soldier and Number Game

题目传送门 1 /* 2 题意:b+1,b+2,...,a 所有数的素数个数和 3 DP+埃氏筛法:dp[i] 记录i的素数个数和,若i是素数,则为1:否则它可以从一个数乘以素数递推过来 4 最后改为i之前所有素数个数和,那么ans = dp[a] - dp[b]: 5 详细解释:http://blog.csdn.net/catglory/article/details/45932593 6 */ 7 #include <cstdio> 8 #include <algorithm>

埃氏筛法&amp;欧拉筛法

埃氏筛法 /* |埃式筛法| |快速筛选素数| |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_p

埃氏筛法(快速筛选n以内素数的个数)

给你一个数n,请问n以内有多少个素数?(n <= 10e7) 一般来说,要是对一个整数进行素数判断,首先想到的是写个函数判断是否为素数,然后调用这个函数,时间复杂度为O(n^(½)),但是要求n以内的素数就略显吃力了. 要是求n以内的素数个数的话,可以用埃式筛选.预处理一下. 先看下面的代码: 1 /* 2 |埃式筛法| 3 |快速筛选素数| |15-7-26| 4 */ 5 #include <iostream> 6 #include <cstdio> 7 using na