LightOJ 1197 LightOJ 1197(大区间素数筛选)

http://lightoj.com/volume_showproblem.php?problem=1197

 

题目大意:

就是给你一个区间[a,b]让你求这个区间素数的个数

 

但a、b的值太大没法直接进行素数筛选(没法开那么大的数组),我们可以将a当做0,将b当做b-a

这样求[a,b]之间就变成了求[0, b - a]之间,这样就可以开数组来筛选

下图是代码式子j = j + prime[i] - a % prime[i]的由来

 

 

#include<stdio.h>
#include<math.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>

using namespace std;

const int N = 1e5 + 10;
const int INF = 0x3f3f3f3f;
typedef long long ll;

int prime[N], f[N], k;
bool Isprime[N];

void Prime()
{
    k = 0;
    memset(Isprime, true, sizeof(Isprime));
    Isprime[1] = false;
    for(int i = 2 ; i < N ; i++)
    {
        if(Isprime[i])
        {
            prime[k++] = i;
            for(int j = 2 ; i * j < N ; j++)
                Isprime[i * j] = false;
        }
    }
}//先用素数筛选法筛选出小范围的素数

int main()
{
    int t, a, b, p = 0;
    scanf("%d", &t);
    Prime();
    while(t--)
    {
        p++;
        memset(f, 0, sizeof(f));
        int num = 0;
        scanf("%d%d", &a, &b);
        int l = b - a;//将a到b转化为从0到b - a
        for(int i = 0 ; i < k && prime[i] * prime[i] <= b ; i++)
        {
            int j = 0;
            if(a % prime[i] != 0)//判断a + j 如果(a + j)% prime[i] != 0,则将a + j筛除
                j = j + prime[i] - a % prime[i];
            if(a + j == prime[i])//如果a + j是素数,则找下一个
                j += prime[i];
            for(; j <= l ; j += prime[i])
                f[j] = 1;//从j开始将含prime[i]因子的数标记(即筛除)
        }
        for(int i = 0 ; i <= l ; i++)
            if(!f[i])
                num++;
        if(a == 1)//如果a从1开始,需要减去一个
            num--;
        printf("Case %d: %d\n", p, num);
    }
    return 0;
}

 

posted @ 2015-11-06 19:01  午夜阳光~  阅读(549)  评论(0编辑  收藏  举报