Eratosthenes筛法

如果要将素数建个表,我们可以从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;
}

那么紫书上引出的问题:
无平方因子的数: 给出正整数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;
} 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值