Problem:
ゴールドバッハ予想

ゴールドバッハ予想とは「6 以上のどんな偶数も、2 つの素数 (*1) の和として表わすことができる」というものです。

たとえば、偶数の 12 は 12 = 5 + 7 、18 は 18 = 5 + 13 = 7 + 11 などと表すことができます。

和が 134 となる 2 つの素数の組み合せをすべて書き出すと、以下の通りとなります。

134 = 3+131 = 7+127 = 31+103 = 37+97 = 61+73 = 67+67

= 131+3 = 127+7 = 103+31 = 97+37 = 73+61

与えられた数が大きくなると、いくらでも素数の組み合せが見つかるような気がします。しかし、現代数学をもってしてもこの予想を証明することも、反例を作ることもできません(*2)。ちょっと不思議な感じがしますね。

そこで、ゴールドバッハ予想を鑑賞するために、偶数 n を入力とし、和が n となる 2 つの素数の組み合せの数を求めるプログラムを作成してください。

和が n となる素数の組み合せの数とは n = p + q かつ p ≤ q であるような正の素数 p, q の組み合せの数です。上の例からわかるように和が 134 となる素数の組み合せは6 個です。

(*1) 素数とは、1 または自分自身以外に約数を持たない整数のことである。なお、1 は素数ではない。

(*2) 2007 年 2 月現在、5×1017 までの全ての偶数について成り立つことが確かめられている。(Wikipedia)

Input

複数のデータセットの並びが入力として与えられます。入力の終わりはゼロひとつの行で示されます。 各データセットとして、１つの偶数 n (6 ≤ n ≤ 1000000) が１行に与えられます。

データセットの数は 500 を超えません。

Output

データセット毎に素数の組み合せの数を１行に出力します。

Sample Input

134
4330
34808
98792
0

Output for the Sample Input

6
72
274
607

Solution in OCaml (judge verdict: Time Limit Exceeded)

open List
let m3_cycle_length = 30
let m3_primes = [5; 3; 2]
let m3_cycle = [6; 4; 2; 4; 2; 4; 6; 2]

let wheel_fact limit =
  let slimit = limit in
  let rec wheel_loop limit n nxt result =
  let get_m3_cycle n =
      nth m3_cycle (n mod ((length m3_cycle)))
  in
  if nxt > limit then tl (sort (fun x y -> if x == 0 then 0
                            else if x > y then 1
                            else -1) (rev (result @ m3_primes)))
  else wheel_loop limit (n + 1) (nxt + (get_m3_cycle n)) (nxt :: result)
  in wheel_loop slimit 0 1 []

let sieve xs =
  let rec sieve_loop xs ys =
    let comp_filter n xs = 
      List.filter (fun x -> x mod n != 0 && n != x) xs 
    in 
    match xs with
      [] -> ys
    | x :: xs -> sieve_loop (comp_filter x xs) (x :: ys)
  in
  sieve_loop xs []

let split xs n =
  let rec split_loop xs n ys =
    if n <= 0 then (ys, xs)
    else split_loop (tl xs) (n - 1) (hd xs :: ys)
  in
  split_loop xs n []

let uniq xs =
  let rec uniq_loop xs ys =
    match xs with
      [] -> ys
    | x :: xs -> uniq_loop (filter (fun (l1, l2) -> l1 != fst x && l2 != snd x) xs) (x :: ys)
  in uniq_loop xs []

let goldbach n =
  let rec gold_loop xs y =
    match xs with
      []      -> y
    | z :: zs -> try
                   if (z * 2) >= n then 
                     if n - z == (find (fun x -> x + z == n) xs)
                     then gold_loop zs (y + 1)
                     else gold_loop zs y
                   else y
                 with
                   Not_found -> gold_loop zs y
  in
  let sieved = sieve (wheel_fact n) in
  gold_loop sieved 0

let () =
  let rec echo_sub () =
    print_int (goldbach(int_of_string(read_line ())));
    print_newline ();
    echo_sub ()
  in
    try echo_sub () with End_of_file -> ()