【今天我们来讲讲筛子】
【埃氏筛的基本思想】
简单来说就是把不大于(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; }
【实际应用】
找素数啊,这还用说吗???