您的位置:首页 > 其它

Eratosthenes筛法

2017-04-13 13:45 501 查看
如果要将素数建个表,我们可以从1~n每个数进行素数判断,如果是则放入数组里。这个效率不算很高,那么有一种算法可以更好实现——Eratosthenes筛法。它的思想就是:对于不超过n的每个非负整数p,删除2p,3p,4p,…,当处理完所有数之后,还没有被删除的就是素数。

#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 10000000;
int vis[maxn];

void Eratosthenes(int n)
{
for(int i=2; i<=n; i++)
{
for(int j=2*i; j<=n; j+=i)
{
vis[j] = 1;
}
}
return;
}
int main()
{
memset(vis,0,sizeof(vis));
int n;
scanf("%d",&n);
Eratosthenes(n);
for(int i=2; i<=n; i++)
{
if(!vis[i])
{
printf("%d ",i);
}
}
return 0;
}


优化一下:在“对于不超过n的每个非负整数p”中,p可以限定为素数——只需在第二重循环前加一个判断if(!vis[i])即可,另外,内层循环不需从i*2开始,因为它已经在i=2时被筛掉了。

#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn = 10000000;
int vis[maxn];
typedef long long L;
void Eratosthenes(L n)
{
memset(vis,0,sizeof(vis));
L m = sqrt(n + 0.5);
for(L i=2; i<=m; i++)
{
if(!vis[i])
{
for(L j=i*i; j<=n; j+=i)
{
vis[j] = 1;
}
}
}
return;
}
int main()
{
L n;
scanf("%lld",&n);
Eratosthenes(n);
for(L i=2; i<=n; i++)
{
if(!vis[i])
{
printf("%lld ",i);
}
}
return 0;
}


那么紫书上引出的问题:

[b]无平方因子的数: 给出正整数n和m,区间[n,m]内的“无平方因子”的数有多少个?

正整数p无平方因子,当且仅当不存在k > 1,使得p是k^2的倍数。

这个问题可以从n开始到m结束,然后一个个数去判断,这样明显爆炸。所以要采用筛素数的方式,从2到√m的素数p中,筛去区间[n.m]内p^2的所有倍数。

代码如下:

#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long LL;
const LL maxn = 1000000000000;
int vis[maxn], ans[maxn];
LL n, m;

int main()
{
int n,m;
memset(vis,0,sizeof(vis));
int t=sqrt(maxn+0.5);
for(int i=2;i<=t;i++) if(!vis[i])
for(int j=i*i; j<=maxn; j+=i) vis[j]=1; //先筛素数

while(scanf("%d%d",&n,&m) == 2 && n && m)
{
int k = floor(sqrt(m+0.5));
memset(ans, 0, sizeof(ans));
for(int i=2; i<=k; i++)
if(!vis[i])
{
int last = m / (i*i);
for(int crt=n/(i*i); crt<=last; crt++)
ans[(i*i)*crt]=1;
}//筛无平方因子数

int count=0;
for(int i=n; i<=m; i++)
{
if(!ans[i])
{
printf("%d ",i);
count++;
}
}
printf("\n");
printf("%d\n",count);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: