Чисел виду 2^x * 3^y, які не перевищують 10^{18}, не так вже й багато. Згенеруємо їх і збережемо в масиві .
Кількість шуканих чисел f(a, b) на відрізку можна знайти за формулою:
Тут f(0, q) позначає кількість чисел виду 2^x * 3^y, які не перевищують . Відповідь на цей запит можна знайти за допомогою бінарного пошуку на масиві .
Приклад
Згенеруємо всі числа виду 2^x * 3^y, які не перевищують .
Відрізку належить чисел (виділені синім).
Відрізку належить чисел (виділені зеленим).
Знайдемо розв'язання для відрізка :
Дійсно, відрізку належать числа шуканого виду:
Реалізація алгоритму
Оголосимо константу MAX = 10^{18} і робочий масив .
#define MAX 1000000000000000000LL
vector<long long> v;Функція preprocess генерує всі числа виду 2^x * 3^y, які не перевищують 10^{18}, і зберігає їх у масиві . Для кожного значення x = 1, 2, 4, 8, ... перебираємо числа y = 1, 3, 9, 27, ... доти, поки x * y < MAX.
void preprocess()
{
long long x = 1, y = 1;
while (x < MAX)
{
while (x * y < MAX)
{
v.push_back(x * y);
y *= 3;
}
x *= 2;
y = 1;
}Відсортуємо числа у масиві .
sort(v.begin(), v.end());
}Основна частина програми. Генеруємо масив чисел виду 2^x * 3^y.
preprocess();Читаємо запит — відрізок . Кількість шуканих чисел на цьому відрізку обчислюється за формулою:
while (scanf("%lld %lld", &a, &b) == 2)
{
res = upper_bound(v.begin(), v.end(), b) – upper_bound(v.begin(), v.end(), a - 1);
printf("%lld\n", res);
}