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 C# (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static readonly int MAX = 1000000;

        static void Main(string[] args)
        {
            StringBuilder sb = new StringBuilder();

            var hamming = new List<int>();
            int j2 = 0, j3 = 0, j5 = 0;
            int x2 = 1, x3 = 1, x5 = 1;
            int min = 0;

            for (int i = 0; min < MAX; i++)
            {
                min = x2;
                min = Math.Min(min, x3);
                min = Math.Min(min, x5);

                hamming.Add(min);

                while (x2 <= min) x2 = 2 * hamming[j2++];
                while (x3 <= min) x3 = 3 * hamming[j3++];
                while (x5 <= min) x5 = 5 * hamming[j5++];
            }

            while (true)
            {
                int[] input = Array.ConvertAll(Console.ReadLine().Split(' '), int.Parse);

                if (input[0] == 0) break;

                int l = LowerBound(hamming, input[0]);
                int r = UpperBound(hamming, input[1]);

                sb.AppendLine((r - l).ToString());
            }
            Console.Write(sb);
        }

        static int LowerBound(List<int> arr, int value)
        {
            int low = 0, high = arr.Count;

            while (low < high)
            {
                int mid = ((high - low) >> 1) + low;

                if (arr[mid] < value) low = mid + 1;
                else high = mid;
            }
            return low;
        }

        static int UpperBound(List<int> arr, int value)
        {
            int low = 0, high = arr.Count;

            while (low < high)
            {
                int mid = ((high - low) >> 1) + low;

                if (arr[mid] <= value) low = mid + 1;
                else high = mid;
            }
            return low;
        }
    }
}