Problem:
Score : 400 points

Problem Statement

We say that a odd number N is similar to 2017 when both N and (N+1)/2 are prime.

You are given Q queries.

In the i-th query, given two odd numbers l_i and r_i, find the number of odd numbers x similar to 2017 such that l_i ≤ x ≤ r_i.

Constraints

1≤Q≤10^5

1≤l_i≤r_i≤10^5

l_i and r_i are odd.

All input values are integers.

Input

Input is given from Standard Input in the following format:

Q
l_1 r_1
:
l_Q r_Q

Output

Print Q lines. The i-th line (1≤i≤Q) should contain the response to the i-th query.

Sample Input 1

1
3 7

Sample Output 1

2

3 is similar to 2017, since both 3 and (3+1)/2=2 are prime.

5 is similar to 2017, since both 5 and (5+1)/2=3 are prime.

7 is not similar to 2017, since (7+1)/2=4 is not prime, although 7 is prime.

Thus, the response to the first query should be 2.

Sample Input 2

4
13 13
7 11
7 11
2017 2017

Sample Output 2

1
0
0
1

Note that 2017 is also similar to 2017.

Sample Input 3

6
1 53
13 91
37 55
19 51
73 91
13 49

Sample Output 3

4
4
1
1
1
2

Solution in Rust (1.42.0) (judge verdict: Accepted)

use std::io;
use std::str::FromStr;
use std::collections::HashSet;
use std::cmp::max;

fn input<T:FromStr>() -> T {
    let mut line: String = String::new();
    io::stdin().read_line(&mut line);
    line.trim().parse().ok().unwrap()
}

fn input_tuple() -> (u64, u64) {
    let mut line: String = String::new();
    io::stdin().read_line(&mut line);
    let vec: Vec<u64> = line.split_whitespace().map(|s| s.parse().unwrap()).collect();
    (vec[0], vec[1])
}

fn prime_numbers(limit: u64) -> HashSet<u64> {
    let mut is_candidate = vec![true; (limit + 1) as usize];
    let mut prime_numbers: HashSet<u64> = HashSet::new();
    for i in 2..(limit+1) {
        if is_candidate[i as usize] {
            prime_numbers.insert(i);
            let mut j = 2;
            while i * j < limit + 1 {
                is_candidate[(i * j) as usize] = false;
                j += 1;
            }
        }
    }
    prime_numbers
}

fn binary_search<F>(mut ok: i32, mut ng: i32, is_ok: F) -> i32
    where
        F: Fn(usize) -> bool
    {
        while (ok - ng).abs() > 1 {
            let mid = (ok + ng) / 2;
            if is_ok(mid as usize) {
                ok = mid;
            } else {
                ng = mid;
            }
        }
        ok
}

fn main() {
    let q: u64 = input();    
    let prime_nums = prime_numbers(200_000);
    let mut candidates: Vec<u64> = Vec::new();
    // println!("len = {}", prime_nums.len());
    for p in &prime_nums {
        if *p != 2 && prime_nums.contains(&((p + 1) / 2)) {
            candidates.push(*p);
        }
    }
    candidates.sort();
    // println!("{:?}", candidates);
    for _ in 0..q {
        let (l, r) = input_tuple();
        let upper_bound = binary_search(candidates.len() as i32, -1, |idx| {
            candidates[idx] >= l
        });
        let lower_bound = binary_search(-1, candidates.len() as i32, |idx| {
            candidates[idx] <= r
        });
        // println!("{}", upper_bound);
        // println!("{}", lower_bound);
        println!("{}", max(0, lower_bound - upper_bound + 1));
    }
}