P1835 素数密度_NOI导刊2011提高(04)

P1835 素数密度_NOI导刊2011提高(04)

题目描述
给定区间L,R,请计算区间中素数的个数。


错误日志: 题目给出的数为 \(MAX_INT\) 很容易越界, 没有开 \(longlong\)


Solution

我们无法再规定时间内处理出 \(1 - R\) 的所有质数
考虑枚举质因数筛去区间内合数, 只需要处理出 \(1 - \sqrt{R}\) 的质数即可
然后在 \([L, R]\) 内, 一个质数 \(p\) 其倍数个数(即筛去合数个数)为 \(\lceil \frac{L}{p} \rceil to \lfloor \frac{R}{p}\rfloor\)
注意这里不能取 \(1\) 否则有可能将质数筛去(\(1 * p = p\)
筛去, 最后枚举区间内没被筛过的数即为质数
记得用小技巧(\(base = L - 1\))将数组范围控制在 \([1, R - L]\) 之间

Code

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#include<climits>
#include<cmath>
#define LL long long
#define REP(i, x, y) for(LL i = (x);i <= (y);i++)
using namespace std;
LL RD(){
    LL out = 0,flag = 1;char c = getchar();
    while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}
    while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
    return flag * out;
    }
const LL maxn = 2000019;
LL L, R, base;
bool isprime[maxn], lastisprime[maxn];
LL prime[maxn];
LL nump;
void get_prime(LL n){
    REP(i, 2, n){
        if(!isprime[i])prime[++nump] = i;
        for(LL j = 1;j <= nump && prime[j] * i <= n;j++){
            isprime[prime[j] * i] = 1;
            if(i % prime[j] == 0)break;
            }
        }
    }
int main(){
    L = RD(), R = RD();base = L - 1;
    get_prime(sqrt(R));
    REP(i, 1, nump){//枚举质数,筛去合数
        LL p = prime[i];
        LL l = L / p, r = R / p;
        if(l * p < L)l++;//向上取整
        if(l == 1)l++;
        //prLLf("l=%d r=%d\n", l, r);
        REP(j, l, r){
            lastisprime[j * p - base] = 1;
            }
        }
    LL ans = 0;
    REP(i, L, R){
        if(!lastisprime[i - base])ans++;
        }
    printf("%lld\n", ans);
    return 0;
    }

转载于:https://www.cnblogs.com/Tony-Double-Sky/p/9817291.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值