LightOj 1197

题目链接:http://lightoj.com/volume_showproblem.php?problem=1197

题意:给你两个数 a b,求区间 [a, b]内素数的个数, a and b (1 ≤ a ≤ b < 231, b - a ≤ 100000).

由于a和b较大,我们可以筛选所有[2, √b)内的素数,然后同时去筛选掉在区间[a, b)的数,用IsPrime[i-a] = 1表示i是素数;

///LightOj1197求区间素数的个数;
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<vector>
using namespace std;
typedef long long LL;
const int oo = 0xfffffff;
const int N = 1e6+5;

int IsPrime[N]; ///IsPrime[i-a] = 1说明i是素数;
int Prime[N]; ///Prime[i] = 1说明i是素数,i比较小;

///对区间[a, b)内的素数进行筛选;
void Segment_sieve(LL a, LL b)
{
    for(int i=0; (LL)i*i<b; i++)
        Prime[i] = 1;
    for(int i=0; i<b-a; i++)
        IsPrime[i] = 1;

    for(int i=2; (LL)i*i<b; i++)
    {
        if(Prime[i])
        {
            for(int j=i+i; (LL)j*j<b; j+=i)///筛选2---sqrt(b)的素数;
                Prime[j] = 0;
            for(LL j=i*max(2LL, (a+i-1)/i); j<b; j+=i)///筛选出[a, b)上是i的倍数的那些数;
                IsPrime[j-a] = 0;
        }
    }
}

int main()
{
    int T, t = 1;
    scanf("%d", &T);
    while(T--)
    {
        LL a, b;
        scanf("%lld %lld", &a, &b);
        Segment_sieve(a, b+1);
        int ans = 0;
        for(int i=0; i<=b-a; i++)
            if(IsPrime[i])ans ++;
        if(a <= 1)///1不是素数,所以要单独处理;
            ans --;
        printf("Case %d: %d
", t++, ans);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/zhengguiping--9876/p/6013399.html