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