Как стать автором
Обновить

Комментарии 86

> в исполнении clang 3.1

А почему не 3.2?
Потому что я пропустил релиз :-) Но замечание справедливое, изменил на 3.2.
Можно использовать ассемблерные вставки?
Ограничений нет, главное в 1024 байта уложитесь :-)
Да.
Можно ли использовать С++11?
Да, на всякий случай укажите свою версию libc++
Сделал в студии — надеюсь прокатит и скомпилится.
Если код корректно написан, и не использует Microsoft-specific типов — то конечно прокатит.
Не уверен __int64 микрософтовский или общий.
unsigned char еще использовал, два типа итого.
__int64 — майкрософтовский, надо использовать int64_t из стандарта плюсов
Нда, поздно увидел поправку «для тех кто в студии». Два раза переотправлял. Так и хочется сказать — «не ругайсо, нащяльника». Ну да ладно.
Эхх, теперь до завтра ждать результатов. Особый, программистский накал страстей.
А можно просто писать long long?
Конечно, да :)
OpenMP/TBB можно использовать?
К сожалению, это уже выпадает за пределы стандартных библиотек.
Так что остаются средства pthreads/C++11
Вопрос, в приведенном пример учитывалось общее время работы программы вместе с вводом данных или только цикла расчета ???
Конечно, с вводом. Да и вообще, какая разница? Мы же читаем только одно число и пишем одно число
Ну как вам сказать, ввод числа руками, ввод из файла и константа это разные по времени обработки методы ввода. Например константа вообще не требует обработки, ввод из файла зависит от скорость диска и т.п. ввод руками вообще зависит от пользователя, (что если я пойду чайку хлебнуть а интер не нажму)
А время как мы видем идет на миллисекунды, это важно, надо либо обозначить как именно все должны делать ввод данных либо ваша time неочем.
Ввод в данном случае не важен, т.к. важно время, занятое у ЦП (колонка user у time).
А с какой точностью оно измеряется? До 1 миллисекунды или хуже? И входит ли в него время на запуск программы?
All times are measured in terms of the number of clock ticks used.

Получается измеряется в тиках
Насчет второго сказать ничего не могу, с никсами почти не имел дела.
Колонка user считает суммарное время на каждом из 4-х ядер. Если распараллеливать, то значение получится в 4 раза больше реального.
Если бы в условиях задачи программа должна была бы принимать число как параметр, никаких проблем бы не было бы.
Очевидно, при тестировании руками никто ничего вводить не будет. :-)
Напишите параметры, с которыми вы компилируете.
clang++ --std=c++11 -O3 -pthread yourfile.cpp
Дядя, вы тут предсчетом не пролезете — 1024 байт = 1024 символов (а то и меньше). Там до 2^30 — не прокатит. Нужно писать блочное решето и генерировать числа в разных потоках, а вообще нужно подумать.
Нужно написать некоторый код, а на остатке байтов предподссчет засунуть, diff-кодирование.
Начнём с однопоточного решета. На Core i5 430UM 1200 Mhz в минуту уложился.
Хм, у меня тест Миллера-Рабина на 2 в 30-ой степени в минуту не помещается.
Хм, а решето Аткина, похоже, справляется.
миллер-рабин тоже в минуту не уложился, а актин что-то с segfault-ом вылетает, может как-то от промежуточного массива избавиться или сократить, но ковыряться глубже сегодня сил нет никаких)
НЛО прилетело и опубликовало эту надпись здесь
std::bitset-ом пользуетесь? у меня и на нем вылетает, где-то на 90 млн., гуглю…
понял, на стеке большие массивы создавать больше не буду)
Попробуйте линейное решето Эратосфена — должно проходить.
Не надо подсказывать! По крайней мере сегодня.
Дак что тут из подсказки. Оно находится по запросу «решето эратосфена за линейное время» за 1 минуту. Просто такой вот тезис.
Для 230-1?
Да.
НЛО прилетело и опубликовало эту надпись здесь
> Побеждает тот, кто напишет самое быстрое решение
Время оценивается какое? Wall clock?
Да, wall clock. Ввод перенаправляется из файла, потому ждать его не придется.
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Маньячина, а теперь разархивированную версию ;-)
Я паковал 8 чисел, взаимно простых с 30 (от 30k+1 до 30k+29) в 1 байт. Выбивал числа так же умножая только на взаимно простые с 30, да еще запоминал таблицу умножения данного простого на числа 1..29 в системе счисления «сдвиг — бит». Плюс борьба с тем, чем массив c решетом не вмещался в кэш.
На i5 2.67МГц для N=10^9 время 0.65 сек.
Но это если решение вообще работает.
И даже на тесте 268588319 укладывается в секунду? ;)
НЛО прилетело и опубликовало эту надпись здесь
результат такой же, время 0.156 s (на i5)
НЛО прилетело и опубликовало эту надпись здесь
А в нечитаемом можно посмотреть? :)

Ещё мне кажется, что для i == 0 можно просто начать с res = (-1) + 2 + 3 + 5 + 7 + 11 + 13; и сэкономить немало байтов кода, например для бОльшей таблицы предподсчета.

Да и саму таблицу можно сделать эффективнее, вместо лестницы if-ов используя массив и цикл.
Правда надо будет отдельно обрабатывать N < 13, суммируя primes[j]
Ещё можно избавиться от относительно дорогого деления, заранее подсчитав:
k[j] = start_from / primes[j];

И после просеивания
k[j] -= block_size;

Не уверен, что улучшит, но вдруг :)

И ещё — просеивание можно делать до sqrt(i), а не до j < primes_count;
НЛО прилетело и опубликовало эту надпись здесь
Ну и распараллелить должно быть несложно.
Хотя ради этого придётся уменьшить таблицу, что в итоге может оказаться невыгодным.
gcc — это вообще другой разговор. Почти всё на gcc будет чуть быстрее. Зачем Вы спрашивали ключи компиляции тогда?
Просто на 268588319 у меня Ваше решение работает больше секунды (на 3,6ГГц) и раза в 3 медленнее, чем 2^30 — 1 (на clang 3.2 в linux x64 с флагом -O3) — из-за предподсчёта.
НЛО прилетело и опубликовало эту надпись здесь
написал так:
1) считаем простые числа в диапазоне от 1 до sqrt(n)
2) так как чисел всего 2^31, определяет рабочий интервал, для которого уже просчитана сумма чисел в предыдущем интервале. интервалов 16, в среднем надо просчитать от начала интервала до его середины. итого 1/32
3) считаем сумму оставшихся простых чисел в рабочем интервале, блочным решетом эратосфена с примитивными оптимизациями чётных значений.

блочное решето с примитивными оптимизациями работает на значениях 2^29 около 0,5 секунд. С предпросчётом от 0,01 до 0,05
Совсем не понял зачем там G, D, F. Если их убрать, код уменьшится на 59 байт.
PS и т.к. сказано, что тестироваться на Linux x86_64 будет, то int64_t можно было на long заменить. 3 байта всего, но может ещё что полезное поместится в суммарные 62 байта. :)
Какие прогнозы на лучшее время?
Думаю, 0.3-0.5 сек на тест.
Да, про явные формулы я забыл. Хакеры-математики, конечно, непобедимы.
Нет-нет, формул тут никаких нет, кроме китайской теоремы об остатках (она максимум даст ускорение в 2-3 раза).
А дзета-функция точно никак не поможет?
Первый раз слышу, детали в студию :-)
Я уже всё забыл. Но она как-то использовалась для оценок количества простых чисел.
Не, дзета-функция не даёт точного количества простых. С её помощью асимптотики находят
Общих формул то может нет, но есть предподсчёт — те же формулы. А с таким слабым ограничением на входные данные и указанием, что тестироваться будет на числах, близких 2^30, его очень резонно делать.
Я бы оценивал по суммарному результату на N случайных числах (одинаковых для всех), двоичные логарифмы которых (с плавающей точкой) распределены равномерно в интервале [20,30]
А потом, для десятки лучших на ещё бОльшем количестве тестов.
Можно спросить почему Вы бы оценивали иначе? И где можно прочитать про метод подборки входных тестовых данных, вамиприведенный?
Дело в том, что заранее зная тесты, можно написать программу, эффективную именно для этого.

Например, программа, печатающая 454396537 независимо от ввода, победит в конкурсе программ, которые будут тестироваться только числом 100000.
Использовать словарь Вам не даст ограничение размера программы в Х байт, где Х равен, как я смею предположить, не больше 1-2К.
Я привёл радикальный пример — словарь не обязательно должен быть полным, чтобы давать хороший результат в заданной узкой области за счёт остальных возможных значений.
Ограничений нет, главное в 1024 байта уложитесь :-)
откоментировал BarsMonster, к тому же выше уже писали любители читов, что «ничего не выходит, мама что делать?».
Нет, лучше, чтобы равномерно были распределены сами числа. Иначе половина примеров окажется меньше 2^25, а там время практически нулевое.
Да, вы правы — обычное равномерное распределение лучше, а я перемудрил.
Ещё интересным был бы рейтинг «по худшему времени» — подозреваю, что после обфускации большинство решений легко укладываются в 1024 байта, поэтому для дальнейшего ускорения логично использовать таблицу предварительно вычисленных значений.

Тесты на небольшом наборе вводов могут легко превратиться в лотерею — и победит тот, кто лучше угадает с таблицей.

А вот если отсортировать участников по лучшему «худшему времени» на одном вводе и потом тщательно проверять лучших, найдя худшее время каждого.
С какой таблицей?
С таблицей предпросчитанных значений, судя по всему.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории