Есть массив, нужно уметь быстро (logn) отвечать на запросы "Сколько чисел в массиве делятся на x". Думал в сторону разряженных таблиц, но никаких результатов. Может кто-нибудь знает идею алгоритма или ссылку где это объясняется.
В массиве чисел 10^6 сами числа 10^9 Так что разложение на множители каждого не сработает.
Другие языки программирования и технологии
Как такое считать быстро?
Структуры, которые позволяют отсекать от множества ненужные элементы, а потом проверять оставшиеся, не подходят:
Предположим, что вам нужно найти чётные числа в массиве, который состоит ТОЛЬКО из чётных. Структура честно выдаст вам весь массив, а потом вам придётся проверять опять же весь.
То есть верхняя граница - O(n) проверок.
Я допускаю, что можно сделать среднюю оценку O(logN), например словари пар: (делитель->битовый массив) . Но считаю, что ответ всё же не в том, чтобы перебирать элементы, когда нужно найти КОЛИЧЕСТВО.
Тут нужно мозговать какую-то альтернативную систему хранения:
Например: число 20 с индексом i хранить как
2: i, i - отсортированный список делителей 2 с кратностью
5: i - аналогично про 5
Это позволит сократить поиск количества при разбиении x на множители.
Нужно будет оперировать списками-множествами.
Это завязано на длину списков, что сопоставимо с logN (даже меньше получится, так как N тут = корень (10^9), а не 10^6)
Предположим, что вам нужно найти чётные числа в массиве, который состоит ТОЛЬКО из чётных. Структура честно выдаст вам весь массив, а потом вам придётся проверять опять же весь.
То есть верхняя граница - O(n) проверок.
Я допускаю, что можно сделать среднюю оценку O(logN), например словари пар: (делитель->битовый массив) . Но считаю, что ответ всё же не в том, чтобы перебирать элементы, когда нужно найти КОЛИЧЕСТВО.
Тут нужно мозговать какую-то альтернативную систему хранения:
Например: число 20 с индексом i хранить как
2: i, i - отсортированный список делителей 2 с кратностью
5: i - аналогично про 5
Это позволит сократить поиск количества при разбиении x на множители.
Нужно будет оперировать списками-множествами.
Это завязано на длину списков, что сопоставимо с logN (даже меньше получится, так как N тут = корень (10^9), а не 10^6)
а как долго у вас считается? если быстрее, вставляйте асм+MMX команды проца
Владимир Свирский
Сказано же - log(n).
log(n) - похоже на дерево. Можно рассортировать их по двоичному дереву, каждый уровень которого представляет делимость на простое число: первый узел - делимость на 2, второй (в обеих ветвях) - на 3, третий (во всех ветвях) - на 5 и т. д. Понадобится O(n) доп. памяти, правда, зато скорость перебора - таки log(n).
Vano Mgebrishvili
Но уровней у нас logn, а простых чисел до 10^9 явно больше.
log(n)?
Тогда вопрос только в том, как его ЗАРАНЕЕ отсортировать/какие доп структуры данных заранее создать. И, раз речь зашла о 10^6 и 10^9, то требования на доп структуры по памяти лучше тоже ограничить O(10^6). Так?
Поэтому разложение на множители заранее не отметайте. В каком-то виде оно может понадобиться, лишь бы требования соблюсти
Тогда вопрос только в том, как его ЗАРАНЕЕ отсортировать/какие доп структуры данных заранее создать. И, раз речь зашла о 10^6 и 10^9, то требования на доп структуры по памяти лучше тоже ограничить O(10^6). Так?
Поэтому разложение на множители заранее не отметайте. В каком-то виде оно может понадобиться, лишь бы требования соблюсти
Taraz
Ладно, пойдем в лоб: идея простая. Выбрать заранее все натуральные числа, являющиеся множителем хотя бы одного из заданных.
И для них сделать map из множителя в ответ задачи.
Потом по этому map-у просто искать ответ. Сложность будет логарифмическая. Вопрос лишь в том, а насколько этот map может оказаться большим.
Вопрос этот не такой простой, но надежда на адекватный размер есть. Я его сюда отправил:
http://otvet.mail.ru/question/171225455
И для них сделать 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;
}
}
можно цикл распараллелить? [чепуха, читать ответы ниже]
std::size_t count = 0;
for (std::size_t i = 0;i < arraysize(input); ++i) {
if (input[i] % x == 0) {
++count;
}
}
можно цикл распараллелить? [чепуха, читать ответы ниже]
Похожие вопросы
- Как вырезать быстро фото?
- Как быстро создать сайт самому
- Как быстро набрать нужную квалификацию, чтобы уйти на удаленку\фриланс и работать из любой точки мира?
- Как быстро изучить c++? Чтобы быстро писать программы под Windows. Знаю только Pascal.
- Как быстро преобразовать старое жесткое форматирование абзацев текста (пробелами) в нормальное?
- Как быстро выучить С++, С, и Pascal
- как быстро раскрутить свой сайт
- В какой программе можно быстро и качественно сделать ретушь женского тела в нижнем белье
- Уважаемые пользователи! Объясните, как технически быстро соединить 2 узла в Corel Draw x6?
- как создать свой сайт. ОТВЕТЬТЕ БЫСТРО ПОЖАЛУЙСТА ОТВЕТЬТЕ БЫСТРО ПОЖАЛУЙСТА
Пусть есть 2 битовые карты делителей на 2 и 3 обычного массива.
Считаем распределение элементов и X случайным в диапазоне 0…10^9.
Таким образом
-- делителей ТОЛЬКО на 2 - 34%
-- делителей только на 3 - 22%
-- делителей на 2 и 3 - 22%
-- не делящихся на 2 и 3 - 22%
поиск можно сократить в 3-5 раз только на двух битовых картах, а если их 8?