Другие языки программирования и технологии

Как такое считать быстро?

Есть массив, нужно уметь быстро (logn) отвечать на запросы "Сколько чисел в массиве делятся на x". Думал в сторону разряженных таблиц, но никаких результатов. Может кто-нибудь знает идею алгоритма или ссылку где это объясняется.

В массиве чисел 10^6 сами числа 10^9 Так что разложение на множители каждого не сработает.
VM
Vano Mgebrishvili
10 928
Структуры, которые позволяют отсекать от множества ненужные элементы, а потом проверять оставшиеся, не подходят:
Предположим, что вам нужно найти чётные числа в массиве, который состоит ТОЛЬКО из чётных. Структура честно выдаст вам весь массив, а потом вам придётся проверять опять же весь.
То есть верхняя граница - O(n) проверок.
Я допускаю, что можно сделать среднюю оценку O(logN), например словари пар: (делитель->битовый массив) . Но считаю, что ответ всё же не в том, чтобы перебирать элементы, когда нужно найти КОЛИЧЕСТВО.

Тут нужно мозговать какую-то альтернативную систему хранения:
Например: число 20 с индексом i хранить как
2: i, i - отсортированный список делителей 2 с кратностью
5: i - аналогично про 5
Это позволит сократить поиск количества при разбиении x на множители.
Нужно будет оперировать списками-множествами.
Это завязано на длину списков, что сопоставимо с logN (даже меньше получится, так как N тут = корень (10^9), а не 10^6)
Эдуард Айвазян
Эдуард Айвазян
11 112
Лучший ответ
Эдуард Айвазян Дополнение про словари пар:
Пусть есть 2 битовые карты делителей на 2 и 3 обычного массива.
Считаем распределение элементов и X случайным в диапазоне 0…10^9.
Таким образом
-- делителей ТОЛЬКО на 2 - 34%
-- делителей только на 3 - 22%
-- делителей на 2 и 3 - 22%
-- не делящихся на 2 и 3 - 22%
поиск можно сократить в 3-5 раз только на двух битовых картах, а если их 8?
а как долго у вас считается? если быстрее, вставляйте асм+MMX команды проца
Владимир Свирский Сказано же - log(n).
log(n) - похоже на дерево. Можно рассортировать их по двоичному дереву, каждый уровень которого представляет делимость на простое число: первый узел - делимость на 2, второй (в обеих ветвях) - на 3, третий (во всех ветвях) - на 5 и т. д. Понадобится O(n) доп. памяти, правда, зато скорость перебора - таки log(n).
(((Hot Boy))) ))Vip((
(((Hot Boy))) ))Vip((
97 305
Vano Mgebrishvili Но уровней у нас logn, а простых чисел до 10^9 явно больше.
log(n)?
Тогда вопрос только в том, как его ЗАРАНЕЕ отсортировать/какие доп структуры данных заранее создать. И, раз речь зашла о 10^6 и 10^9, то требования на доп структуры по памяти лучше тоже ограничить O(10^6). Так?

Поэтому разложение на множители заранее не отметайте. В каком-то виде оно может понадобиться, лишь бы требования соблюсти
Ta
Taraz
19 662
Taraz Ладно, пойдем в лоб: идея простая. Выбрать заранее все натуральные числа, являющиеся множителем хотя бы одного из заданных.
И для них сделать map из множителя в ответ задачи.

Потом по этому map-у просто искать ответ. Сложность будет логарифмическая. Вопрос лишь в том, а насколько этот map может оказаться большим.

Вопрос этот не такой простой, но надежда на адекватный размер есть. Я его сюда отправил:

http://otvet.mail.ru/question/171225455
ммм, может не так понимаю, но если числа целые O(n):

std::size_t count = 0;
for (std::size_t i = 0;i < arraysize(input); ++i) {
if (input[i] % x == 0) {
++count;
}
}

можно цикл распараллелить? [чепуха, читать ответы ниже]
Евгений Рожин
Евгений Рожин
3 437