求大区间质数个数

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 , ........都不是质数 。


[cpp]  view plain  copy
 print ?
  1. const int Max_N = 500000 ;  
  2. LL   prime[Max_N] ;  
  3. int  prime_size ;  
  4. bool isnot_prime[Max_N+10] ;  
  5. int  dp[Max_N+10] ;  
  6. void  make_prime(){  
  7.       prime_size = 0 ;  
  8.       memset(isnot_prime , 0 , sizeof(isnot_prime)) ;  
  9.       dp[0] = dp[1] = 0 ;  
  10.       for(int i = 2 ; i <= Max_N ; i++){  
  11.           if(!isnot_prime[i])  
  12.               prime[prime_size++] = i ;  
  13.           for(int j = 0 ; j < prime_size && prime[j] * i <= Max_N; j++){  
  14.               isnot_prime[i*prime[j]] = 1 ;  
  15.               if(i % prime[j] == 0)  
  16.                   break ;  
  17.           }  
  18.           dp[i] = prime_size ;  
  19.       }  
  20. }  
  21.   
  22. bool visited[1000000+8] ;  
  23.   
  24. int Ans(int L , int R){  
  25.     if(R <= Max_N)  
  26.         return dp[R] - dp[L-1] ;  
  27.     int ans = 0 ;  
  28.     if(L <= Max_N){  
  29.         ans = dp[Max_N] - dp[L-1] ;  
  30.         L   = Max_N + 1 ;  
  31.     }  
  32.     int len = R - L + 5 ;  
  33.     LL start ;  
  34.     memset(visited,0,sizeof(visited)) ;  
  35.     for(int i = 0 ; i < prime_size && prime[i]*prime[i] <= R ; i++){  
  36.         start = L/prime[i]*prime[i] ;  
  37.         if(start < L)  
  38.             start += prime[i] ;  
  39.         for(LL j = start ; j <= R ; j += prime[i])  
  40.             visited[j-L] = 1 ;  
  41.     }  
  42.     for(int i = 0 ; i <= R-L ; i++)  
  43.         ans += !visited[i] ;  
  44.     return ans ;  
  45. }  
  46.   
  47. int main(){  
  48.     make_prime() ;  
  49.     LL L , R ;  
  50.     while(cin>>L>>R){  
  51.          printf("%d\n" , Ans(L , R)) ;  
  52.     }  
  53.     return 0 ;  
  54. }  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值