Problem:
ハミング数

1 に 2, 3, 5 を何回か (0 回以上) かけ算して得られる数をハミング数 (Hamming numbers) と呼びます。例えば、

1

1 × 2 × 2 = 4

1 × 2 × 2 × 3 × 5 × 5 = 300

などはハミング数ですが、11, 13, 14 などはハミング数ではありません。

ハミング数はどれも 60 のべき乗を割り切る(例えば、54 は 603 = 21600 を割り切る) ので、時刻など 60 進法の計算には都合の良い数として昔から知られていました。また、楽器の調律に用いる音階の一つである純正律では、音の周波数の比が 24, 27, 30, 32, 36, 40, 45, 48 というハミング数からなる数列になります。

整数 m、n を入力とし、m 以上 n 以下のハミング数の個数を出力するプログラムを作成してください。

Input

複数のデータセットの並びが入力として与えられます。入力の終わりはゼロひとつの行で示されます。

各データセットとして、２つの整数 m と n (1 ≤ m, n ≤ 1000000, m ≤ n) が空白区切りで１行に与えられます。

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

Output

データセットごとに m 以上 n 以下のハミング数の個数を１行に出力します。

Sample Input

3 8
1 27
1 86
0

Output for the Sample Input

5
17
31

Solution in Scala (judge verdict: Accepted)

import scala.annotation.tailrec
import scala.collection.{immutable, mutable}
import scala.io.StdIn._
object Main extends App {

  val isHamming = Array.fill(1000001){true}
  for (p ← prime(1000000).drop(3)) {
    for (j ← p until isHamming.length by p) {
      isHamming(j) = false
    }
  }
  val hammingNumbers = isHamming.indices.drop(1).filter(isHamming).toArray
  loop()
  @tailrec def loop(): Unit = {
    readLine.trim.split(' ').map(_.toInt) match {
      case Array(m, n) ⇒ println(upperBound(hammingNumbers, n) - lowerBound(hammingNumbers, m))
        loop()
      case _ ⇒
    }
  }

  def lowerBound(array: Array[Int], target: Int): Int = {
    var left = 0
    var right = array.length
    while (left < right){
      val mid = (left + right) / 2
      if (array(mid) < target) left = mid + 1
      else right = mid
    }
    right
  }
  def upperBound(array: Array[Int], target: Int): Int = {
    var left = 0
    var right = array.length
    while(left < right) {
      val mid = (left + right) / 2
      if (array(mid) <= target) left = mid + 1
      else right = mid
    }
    right
  }
  def prime(upperLimit: Int): Seq[Int] = {
    val isPrime = Array.fill(upperLimit + 1){true}
    for (i ← 2 to math.sqrt(upperLimit).round.toInt) {
      if (isPrime(i)) for (j ← i * i to upperLimit by i){
        isPrime(j) = false
      }
    }
    (2 to upperLimit).filter(isPrime)
  }
}