Для этого есть более эффективное решение. Но это немного сложно. Вот шаги, чтобы добраться до необходимой структуры данных.
Определить тип данных prime_factor
, который является структурой, которая содержит простое число и число.
Определите тип данных prime_factorization
, который является вектором первого типа данных в возрастающем размере простых чисел. Это может хранить факторизацию числа.
Напишите функцию, которая принимает число и превращает ее простую факторизацию в prime_factorization
Напишите функцию, которая принимает 2 prime_factorization
векторов и объединяет их в факторизацию произведения двух.
Для каждого числа в вашем массиве вычислите его простую факторизацию. Это сохраняется в массиве.
Для каждой пары в вашем массиве вычислите простую факторизацию продукта. Нам понадобится только половина из них. Поэтому элементы 0, 1
go в одну факторизацию, 2, 3
в следующую и т. Д.
Повторите шаг 6 O(log(N))
раз. Таким образом, у вас есть вектор факторизации каждого числа, пар, четверок, восьмерок и так далее. Это приводит к приблизительно 2N
предварительно вычисленным векторам факторизации. Большинство векторов небольшие, хотя некоторые могут иметь размер до O(D)
(где D
- количество различных простых чисел). Большинство слияний должно быть очень, очень быстрым.
И теперь у вас есть все подготовленные данные. Это не может занять более чем O(log(N))
раз пространства, в котором хранятся основные факторы, требуемые самим собой. (Однако обычно это меньше, потому что повторы среди небольших простых чисел собираются вместе в один prime_factor
.)
Любой диапазон представляет собой объединение не более O(log(N))
этих вычисленных векторов. Например, диапазон 10..25
можно разбить на 10..11, 12..15, 16..24, 25
. Расположите эти интервалы от наименьшего к наибольшему и объедините их. Затем вычислите ваш ответ из результата.
Точный анализ сложен. Но я уверяю вас, что время запроса ограничено выше O(Q * D * log(N))
и обычно намного меньше этого.
ОБНОВЛЕНИЕ :
Как вы находите эти интервалы?
Ответ заключается в том, что вам нужно определить число, кратное наибольшей степени 2 в диапазоне, а затем заполнить обе стороны оттуда. И вы выясните это путем деления на 2 (округления вниз), пока диапазон не станет длины 1. Затем умножьте верхнюю границу на 2, чтобы найти эту среднюю точку.
Например, если ваш диапазон был 35-53
вы начнете с деления на 2, чтобы получить 35-53
, 17-26
, 8-13
, 4-6
, 2-3
. Это было 2^4
, на которое мы разделились. наша сила 2 средней точки 3*2^4 = 48
. Наши интервалы выше этой средней точки тогда равны 48-52, 53-53
. Наши интервалы ниже 40-47, 36-39, 35-35
. И каждый из них имеет степень 2 и начинается с числа, кратного этой степени 2.