大区间质数个数

http://acm.hit.edu.cn/hoj/problem/view?id=2276

Given an integer interval [L, R](L <= R <= 2147483647, R - L <= 1000000), please calculate the number of prime(s) in the interval.

Input

Multiple cases.
There is one line in each case, which contains two integer: L, R.

Output

There is only one line for each case, which contains the number of prime(s) in the interval.

Sample Input
2 11
Sample Output
5


做下标映射:

   L       -> 0 

  L+1   -> 1

 L+2    -> 2

.......

   R      -> R - L <= 1000000

  sqrt(R) < 500000

  那么 R的真因子一定< 500000 。

1  、   R < 500000  直接计算

2 、  L < 500000 < R  ==>

      [L , 500000]     转1

+  [500001 , R]       转3

3、用质数p = { 2 ,3 ,5 ,7, .......}.

   去筛选  [L ,R]  , 找到    {x|x >=L  且 x % p = 0}     的最小值start 。

   那么  start ,  start+p ,  start +2p .........  都不是质数

即 下标      start-L , start+p-L , ........都不是质数 。


const int Max_N = 500000 ;
LL   prime[Max_N] ;
int  prime_size ;
bool isnot_prime[Max_N+10] ;
int  dp[Max_N+10] ;
void  make_prime(){
      prime_size = 0 ;
      memset(isnot_prime , 0 , sizeof(isnot_prime)) ;
      dp[0] = dp[1] = 0 ;
      for(int i = 2 ; i <= Max_N ; i++){
          if(!isnot_prime[i])
              prime[prime_size++] = i ;
          for(int j = 0 ; j < prime_size && prime[j] * i <= Max_N; j++){
              isnot_prime[i*prime[j]] = 1 ;
              if(i % prime[j] == 0)
                  break ;
          }
          dp[i] = prime_size ;
      }
}

bool visited[1000000+8] ;

int Ans(int L , int R){
    if(R <= Max_N)
        return dp[R] - dp[L-1] ;
    int ans = 0 ;
    if(L <= Max_N){
        ans = dp[Max_N] - dp[L-1] ;
        L   = Max_N + 1 ;
    }
    int len = R - L + 5 ;
    LL start ;
    memset(visited,0,sizeof(visited)) ;
    for(int i = 0 ; i < prime_size && prime[i]*prime[i] <= R ; i++){
        start = L/prime[i]*prime[i] ;
        if(start < L)
            start += prime[i] ;
        for(LL j = start ; j <= R ; j += prime[i])
            visited[j-L] = 1 ;
    }
    for(int i = 0 ; i <= R-L ; i++)
        ans += !visited[i] ;
    return ans ;
}

int main(){
    make_prime() ;
    LL L , R ;
    while(cin>>L>>R){
         printf("%d\n" , Ans(L , R)) ;
    }
    return 0 ;
}







你可能感兴趣的:(大区间质数个数)