M - Help Hanzo
阿新 • • 發佈:2018-11-15
題目連結: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; }