Pull to refresh

Comments 86

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

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

Ещё мне кажется, что для 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;
UFO just landed and posted this here
Ну и распараллелить должно быть несложно.
Хотя ради этого придётся уменьшить таблицу, что в итоге может оказаться невыгодным.
gcc — это вообще другой разговор. Почти всё на gcc будет чуть быстрее. Зачем Вы спрашивали ключи компиляции тогда?
Просто на 268588319 у меня Ваше решение работает больше секунды (на 3,6ГГц) и раза в 3 медленнее, чем 2^30 — 1 (на clang 3.2 в linux x64 с флагом -O3) — из-за предподсчёта.
UFO just landed and posted this here
написал так:
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 байта, поэтому для дальнейшего ускорения логично использовать таблицу предварительно вычисленных значений.

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

А вот если отсортировать участников по лучшему «худшему времени» на одном вводе и потом тщательно проверять лучших, найдя худшее время каждого.
С таблицей предпросчитанных значений, судя по всему.
Sign up to leave a comment.

Articles