【算法杂谈】埃氏素数筛

【今天我们来讲讲筛子】

【埃氏筛的基本思想】

简单来说就是把不大于(n为数据范围)以内的素数的倍数全都去掉,那么剩下的就是2~n之间的素数了。

【举个例子】

我们假设现在n是25。

第一步:先把2作为筛子,那么所有2的倍数都被筛掉了。

则当前序列为:2 3 5 7 9 11 13 15 17 19 21 23 25

第二步:剩下的序列中第一个素数是3,将序列中3的倍数划掉。

则当前序列为:2 3 5 7 11 13 17 19 23 25

25仍然大于3的平方,所以我们还要继续筛

现在序列中第一个素数是5,同样将序列中5的倍数划掉。

则当前序列为:2 3 5 7 11 13 17 19 23

因为23小于5的平方,跳出循环

So 最后的答案就是:2 3 5 7 11 13 17 19 23 啦

是不是很简单?

哦,忘说了,这种方法的时间复杂度是O(n log n)。

想要更快的吗,还有线性筛呢!!!

【参考代码】

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const long long maxn=10000007+10;
const long long maxp=700000;
int vis[maxn];
long long prime[maxp];
long long n;

long long gen()
{
    long long m=(long long)sqrt(n+0.5);
    memset(vis,0,sizeof(vis));
    vis[2]=0;
    for(long long i=3;i<=m;i=i+2)
	{
        if(!vis[i])for(long long j=i*i;j<=n;j+=i) vis[j]=1;
        if(i*i>n)break;
    }
    long long c=1;
    prime[0]=2;
    for(long long i=3;i<=n;i=i+2) if(!vis[i]) prime[c++]=i;
    return c;
}
int main()
{
    long long c;
    cin>>n;
    c=gen();
    for(long long i=0;i<c;i++) printf("%lld ",prime[i]);
    cout<<endl<<c;
    return 0;
}

【实际应用】

找素数啊,这还用说吗???

时间: 2024-10-27 04:47:58

【算法杂谈】埃氏素数筛的相关文章

埃氏素数筛法(Eratosthenes)

埃氏筛法: 对于每一个小于n的非负整数p,删去2p,3p,4p......,当处理完所有数后,还没有删除的就是素数. 想法:用a记录素数表,a[i]=1表示不是素数,a[i]=0表示是素数. #include <iostream> #include <algorithm> #include <cmath> using namespace std; int n,m,a[10000005],t; int main() { a[1]=1; cin>>n>&g

区间内素数的个数(也要用到埃氏算法)

题目大意:给定正整数a和b,请问区间[a,b)内有多少个素数 限制条件:a<b<=10^12    b-a<=10^6 样例: 22 37 3 22801763489 22801787297 1000 思路:由于b以内的合数的最小质因数一定不超过根号b,所以如果有根号b以内的素数表的话,就可以用埃氏算法运用在[a,b)上了.  也就是说,先分别做好[2,根号b)的表和[a,b)的表, 然后从[2,根号b)的表中筛得素数的同时,也将其倍数从[a,b)的表中划去,最后剩下的就是[a,b)以内

埃氏筛法(素数筛)

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

素数表的获取(埃氏筛和欧拉筛)

Eratosthenes筛法(埃氏筛) 时间复杂度:O(nlognlogn) 思路 代码 const int maxn=1e6+10; //表长 int prime[maxn],cnt=0; //prime数组存放所以素数,cnt为素数个数 bool st[maxn]; //false为素数 void get_prime(int n){ for(int i=2;i<=n;i++){ if(!st[i]){ prime[cnt++]=i; //把素数i存到prime数组中 for(int j=i+

素数筛(1) 埃氏筛法

其原理就是先将2-n之内的所有数存在一个数组里,初始化所有数全为素数,然后从2开始寻找,只要标记是素数便将他的所有倍数的标记都改为合数,依次类推.时间复杂度为O(nloglogn). 代码实现 1 void prime_table() 2 { 3 for(int i=2;(LL)i<=n;i++) prime[i]=1; 4 for(int i=2;(LL)i*i<=n;i++) 5 if(prime[i]) for(LL j=i*i;j<=n;j+=i) prime[j]=0; 6 }

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

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

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

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

埃氏筛选 - 素数的个数

#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> using namespace std; const int maxn = 1000000 + 200; int prime[maxn]; //第i个素数 bool is_prime[maxn + 1]; //is_prime[i]位true, 表示i是素数 void solve(); int sieve

分拆素数和 埃氏筛法

分拆素数和 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