1. 程式人生 > >zcmu 1022 Primes on Interval(線性篩+二分)

zcmu 1022 Primes on Interval(線性篩+二分)

【題目】

【題意】

給出整數a,b ,k,a,b代表[a,b]區間,求出最小的長度l,使得[a,b]區間內任何一個長度為l的連續區間中素數的數量>=k.

【思路】

用線性篩法篩出[1,1e6]中的素數,用一個數組cou[i]記錄1到i的素數數目,便於進行某個區間素數數目的計算。由於答案具有單調性,考慮用二分判斷並輸出最小長度l。

【程式碼】

#include <stdio.h> 
#include <string.h> 
#include <math.h> 
#include <stdlib.h> 
#include <stack> 
#include <queue> 
#include <algorithm> 
#include <iostream> 
#define mem(a) memset(a,0,sizeof(a)) 
#define go(i,a,b) for(int i=a;i<=b;i++) 
#define og(i,a,b) for(int i=a;i>=b;i--) 
using namespace std; 
const int N=1e6; 
const int inf=0x3f3f3f3f; 
typedef long long ll; 
typedef unsigned long long ull; 
bool num[N+5]; 
int prime[N+5],cou[N+5]; 
int a,b,k; 
void isprime() 
{ 
    memset(num,true,sizeof(num)); 
    num[1]=false; int c=0; 
    for(int i=2;i<=N;i++) 
    { 
        if(num[i]) prime[c++]=i; 
        for(int j=0;j<c&&i*prime[j]<=N;j++) 
        { 
            num[prime[j]*i]=false; 
            if(i%prime[j]==0) break; 
        } 
    } 
} 
void init() 
{ 
    isprime(); mem(cou); 
    for(int i=2;i<=N;i++) 
        if(num[i]) cou[i]=cou[i-1]+1; 
        else cou[i]=cou[i-1]; 
} 
int cul(int l) 
{ 
    for(int i=a;i<=b-l+1;i++) 
        if(cou[i+l-1]-cou[i-1]<k) return 0; 
    return 1; 
} 
main() 
{ 
    init(); 
    while(~scanf("%d%d%d",&a,&b,&k)) 
    { 
        int l=1,r=b-a+1,mid,f=0; 
        while(l<=r) 
        { 
            mid=(l+r)/2; 
            if(cul(mid)) r=mid-1,f=1; 
            else l=mid+1; 
        } 
        if(f) printf("%d\n",l); 
        else printf("-1\n"); 
    } 
}