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 proconio::input;
#[allow(unused_imports)]
use proconio::marker::{Bytes, Chars};
#[allow(unused_imports)]
use std::cmp::{min, max};

fn sieve_of_eratosthenes(n: usize) -> Vec<usize> {
    // spf:
    // store smallest prime factor of number
    // 最小の素因数を格納
    // is_prime:
    // 配列番号が素数であるかどうかを示す
    let mut spf = vec![None; n+1];
    let mut is_prime = vec![true; n+1];
    let mut primes = Vec::new();

    // 0 と 1 は素数ではない
    is_prime[0] = false;
    is_prime[1] = false;

    for i in 2..n+1 {
        // is_prime[i]:
        // それ以下の素数で割り切られていなければ True となる
        if is_prime[i] {

            // この if 文より i は素数なので
            primes.push(i);

            // 素数はそれ自身の最も小さい素因数であるから
            spf[i] = Some(i);
        }

        // 全ての prime の倍数(prime * i)を取り除く
        for prime in &primes {
            // prime が i の最も小さい因数よりも大きくなってしまったら探索終了
            if i * prime >= n + 1 || prime > &spf[i].unwrap() {
                break;
            }

            is_prime[i * prime] = false;

            // i * primes[j] の最も小さい素数は primes[j] 自身
            spf[i * prime] = Some(*prime);
        }
    }
    primes
}

fn main() {
	input! {
		q: usize,
		lr: [(usize, usize); q],
	}


	// 100000までの素数テーブルを作成
	// r1～rqまでの最大値rmaxを求める
	// 0-rmaxまでの各数が2017似数かどうかを求め、
	// 累積和テーブルsを作る
	// あとは各クエリの答えを出力

	let p = sieve_of_eratosthenes(100000);
	let mut pd = vec![false; 100000];
	for i in 0..p.len() {
		pd[p[i]] = true;
	}

	let mut rmax = 0;
	for i in 0..q {
		rmax = max(rmax, lr[i].1); 
	}

	let mut s = vec![0; rmax+1];	// s[0]=0, s[1]=0
	for i in (3..=rmax).step_by(2) {
		if pd[i] && pd[(i+1)/2] {
			s[i] = s[i-2] + 1;
		}
		else {
			s[i] = s[i-2];
		}
	}

	//println!("{:?}", s);

	for i in 0..q {
		let l;
		if lr[i].0 == 1 {
			l = 0;
		}
		else {
			l = lr[i].0 - 2;
		}
		println!("{}", s[lr[i].1] - s[l]);
	}
}