Хорошо, поскольку (согласно вашему комментарию) в массиве может быть только 10 5 элементов, это также максимальный count каждого возможного значения в массиве.
Таким образом, вы могли бы предварительно рассчитать все эти факториалы в массив и использовать их для вычислений.
Вероятно, лучший способ сделать это - написать метапрограмму, которая создает значения в структуру C ++, которую вы затем можете включить в свой собственный код (a) . Структура будет выглядеть примерно так:
unsigned int facMod10p7[] = {
0,
1,
2,
:
/* whatever (10^5)! % 1000000007 is */
};
Как только вы это получите, поиск каждого факториала будет O (1). Чтобы выполнить запрос, вы просто перебираете массив (от L
до R
), считая количество уникальных значений.
Это, вероятно, лучше всего сделать с map<unsigned int, unsigned int>
с первым полем, являющимся значением (при условии, что значения без знака здесь, но вы могли бы также легко сделать это со знаком), а вторым - с количеством раз, когда это произошло.
В случае L2/R4
с {4, 2, 4}
вы получите карту таким образом:
{ [2] = 1, [4] = 2 }
Тогда нужно просто повторить поиск факториала для каждого счета и взять произведение их всех.
Так как это O (1) поиск / умножение в цикле O (n), результирующая сложность будет O (n).
(a) Например, программе Python для вывода первых 10000 факториалов требуется около 30 секунд на моем компьютере для генерации всей таблицы (в моей среде WSL, не обязательно известной своим слепым I / O скорость, по крайней мере, до следующего релиза в ближайшее время):
real 0m29.137s
user 0m28.438s
sys 0m0.547s
Код, если вы хотите сделать свои собственные тесты, это:
print('static unsigned int facMod10p7[] = {\n 0,')
val = 1
mult = 2
for i in range(100000):
print(' {},'.format(val) % 1000000007)
val *= mult
mult += 1
print(');')