1. 程式人生 > >M - Help Hanzo

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;
}