M - Help Hanzo

题目链接:https://cn.vjudge.net/contest/70017#problem/M

题目大意:就是素数筛,但是要筛的数很大,但是筛的区间很小。

题解:先求出1e6的素数筛,然后看区间有三种可能,第一种是在1e6的范围里面,直接输出就行了,第二种就是最大的超过了1e6但是最小的小于1e6,第三种就是最小的超过了1e6,第二种和第三种的方法就是跟正常素数筛一样的求法,但是要利用映射的方法来统计区间内的素数。

代码:

#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <queue>

using namespace std;
int Isprime[1000009];
int book[1000000],top=0,num;
bool vis[1000010];
void prime()
{
    Isprime[0]=1;
    Isprime[1]=1;
    for(int i=2;i<=1000005;i++)
    {
        if(Isprime[i]==0)
        {
            book[++top]=i;
            int x=i*2;
            for(int j=3;x<=1000005;j++)
            {
                Isprime[x]=1;
                x=i*j;
            }
        }
    }
}
void solve(int a,int b)
{
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=top;i++)
    {
        int x=book[i];
        if(x>=b) break;
        for(int j=a/x;j<=b/x+1;j++)
        {
            if(j<=1) continue;
            if(j*x>=a&&j*x<=b&&vis[j*x-a]==0)
            {
                vis[j*x-a]=1;
                num++;
            }
        }
    }
}
int main()
{
    prime();
    int t,a,b;
    scanf("%d",&t);
    for(int k=1;k<=t;k++){
    scanf("%d %d",&a,&b);
    num=0;
    if(b>1e6){
    solve(a,b);
    printf("Case %d: %d\n",k,b-a+1-num);
    }
    else
    {
        int ans=0;
        for(int i=1;i<=top;i++)
        {
            if(book[i]>=a&&book[i]<=b)
            ans++;
        }
        printf("Case %d: %d\n",k,ans);
    }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/The_city_of_the__sky/article/details/83446938