【数论】埃氏筛法&&CODE[VS] 3223 素数密度 = =

DQS真是太神辣!
学长博客地址:http://blog.csdn.net/loi_dqs/article/details/49486467(点击进入异♂世界)

埃氏筛法:

时间复杂度O(nloglogn)
(mdCSDN分分钟崩溃,重写第四次QAQ)
想要得到n以内所有质数,应筛去sqrt(n)以内的所有质数的倍数
为什么呢
因为,我们假设a = sqrt(n),所以有a^2 == n,因此一个自然数的因数,如果大于sqrt(n),则必定有一个因数是小于sqrt(n)的,反之亦然,所以只需要找到小于等于sqrt(n)的质数即可,减少了运算次数,提高了效率。

对于3223,这个题,一个问题就是l,r范围有点大,直接用数组存肯定会炸掉,所以我们就不存了!!!,直接在sqrt(n)以内筛出质数,再用筛出来的质数在区间[l,r]中筛出合数。
这里我们让j = max(2,(l+i-1)/i)*i,作为枚举的下界,(i是你之前所筛出的一个质数),之所以在2与(l+i-1)/i之间取max,是因为2是最小的质数同时也是普遍i的最小倍数(因为i*1没必要举到),一定不能小于2,而(l+i-1)/i则是大于等于l的i的最小倍数,这么做的话是可以减少运算步数,最后将这个倍数乘以i本身,再在循环的时候,每次加i,就可以很快地找出合数了

还有就是在用质数筛合数的时候,别忘了在2后加上 -ll后缀,2ll表示long long型的常数2

垃圾题代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>

const long long maxn = 1233333;

using namespace std;
typedef long long LL;

LL l,r;
LL ans;
LL n;
bool pri[maxn];
bool check[maxn];

LL read()
{
    char ch;
    LL data = 0;
    LL f = 1;
    while(ch <'0'|| ch >'9')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();

    }
    do{
        data = data*10+ch-'0';
        ch = getchar();
    }while(ch >='0'&&ch <='9');
    data *= f;
return data;
}

inline void prime(LL x)
{
    memset(check,0,sizeof(check));
    for(LL i = 2;i <= sqrt(x);i++)
    {
        if(check[i] != 1)
        {
            for(LL j = i*i;j <= sqrt(x);j += i)
            {
                check[j] = 1;
            }
            for(LL j=max(2ll,(l+i-1)/i)*i;j<=r;j+=i) 
            {
                pri[j-l]=1;
            }
        } 
    }
}

int main()
{
    l = read();
    r = read();
    prime(r);
    for(LL i = 0;i <= r - l;i++)
        if(!pri[i]) 
            ans++;
    printf("%lld\n",ans);
return 0;
}

THE END

By Peacefuldoge
http://blog.csdn.net/loi_peacefuldog

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值