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