Если задано неотрицательное целое число N
, выведите наименьшее нечетное положительное целое число, являющееся сильным псевдослучестным, для всех первых N
простых оснований.
Это последовательность OEIS A014233 .
Тестовые случаи (одноиндексированные)
1 2047
2 1373653
3 25326001
4 3215031751
5 2152302898747
6 3474749660383
7 341550071728321
8 341550071728321
9 3825123056546413051
10 3825123056546413051
11 3825123056546413051
12 318665857834031151167461
13 3317044064679887385961981
Контрольные примеры для N > 13
недоступны, поскольку эти значения еще не найдены. Если вам удастся найти следующие термины в последовательности, обязательно отправьте их / их в OEIS!
правила
- Вы можете выбрать значение
N
с нулевым или одним индексом. - Для вашего решения приемлемо работать только для значений, представляемых в целочисленном диапазоне вашего языка (например,
N = 12
для 64-разрядных целых чисел без знака), но ваше решение теоретически должно работать для любого ввода с допущением, что ваш язык поддерживает целые числа произвольной длины.
Фон
Любое положительное четное целое число x
может быть записано в форме, x = d*2^s
где d
нечетно. d
и s
может быть вычислено путем многократного деления n
на 2 до тех пор, пока частное не перестанет делиться на 2. d
Является ли это конечное частное и s
числом, когда 2 делит n
.
Если натуральное число n
является простым, то маленькая теорема Ферма утверждает:
В любом конечном поле Z/pZ
(где p
есть простое число) единственными квадратными корнями 1
являются 1
и -1
(или, что эквивалентно, 1
и p-1
).
Мы можем использовать эти три факта, чтобы доказать, что одно из следующих двух утверждений должно быть истинным для простого числа n
(где d*2^s = n-1
и r
является некоторым целым числом [0, s)
):
Тест на примитивность Миллера-Рабина работает путем проверки контрапозитива по приведенному выше утверждению: если существует основание a
, в котором оба вышеуказанных условия являются ложными, то n
это не простое число. Эта база a
называется свидетелем .
Теперь тестирование каждой базы [1, n)
было бы непомерно дорогим по времени вычислений для больших n
. Существует вероятностный вариант теста Миллера-Рабина, который проверяет только некоторые случайно выбранные базы в конечном поле. Однако было обнаружено, что тестирование только простых a
оснований является достаточным, и, таким образом, тест может быть выполнен эффективным и детерминистическим способом. В действительности, не все основные основания должны быть проверены - требуется только определенное число, и это число зависит от размера значения, проверяемого на первичность.
Если тестируется недостаточное количество простых базисов, тест может давать ложноположительные значения - нечетные составные целые числа, когда тест не может доказать их составность. В частности, если основание a
не может доказать композицию нечетного составного числа, это число называется сильным псевдослучайным к основанию a
. Эта задача состоит в том, чтобы найти нечетные составные числа, которые являются сильными псевдопримерами для всех оснований, меньших или равными первому N
числу (что эквивалентно тому, чтобы сказать, что они являются сильными псевдопримями для всех простых оснований, меньших или равными N
первому числу) ,
Ответы:
C
349295277267255 байтПринимает ввод на основе 1 в stdin, например:
Конечно, в ближайшее время он не обнаружит никаких новых значений в последовательности, но он выполняет свою работу. ОБНОВЛЕНИЕ: теперь еще медленнее!
a^(d*2^r) == (a^d)^(2^r)
)__int128
, который короче, чемunsigned long long
при работе с большими числами! Также на машинах с прямым порядком байтов printf с%llu
все еще работает отлично.Менее уменьшенная
(Устаревшее) Разбивка
Как уже упоминалось, это использует ввод на основе 1.
Но для n = 0 он выдает 9, что соответствует связанной последовательности https://oeis.org/A006945 .Уже нет; сейчас висит на 0.Должно работать для всех n (по крайней мере, пока выход не достигнет 2 ^ 64), но невероятно медленно. Я проверил это на n = 0, n = 1 и (после долгого ожидания), n = 2.
источник
Python 2,
633465435292282275256247 байт0 индексированные
Преобразование из функции в программу как-то экономит несколько байтов ...
Если Python 2 дает мне более короткий способ сделать то же самое, я собираюсь использовать Python 2. Деление по умолчанию является целочисленным, так что более простой способ деления на 2 и
print
не требует скобок.Попробуйте онлайн!
Python известен своей медлительностью по сравнению с другими языками.
Определяет пробное деление теста на абсолютную корректность, затем многократно применяет критерий Миллера-Рабина до тех пор, пока не будет найден псевдопригодность.
Попробуйте онлайн!
РЕДАКТИРОВАТЬ : наконец-то игра в гольф ответ
РЕДАКТИРОВАТЬ : Используется
min
для теста первичности пробного деления и изменил его на alambda
. Менее эффективно, но короче. Также не мог помочь себе и использовал пару побитовых операторов (без разницы в длине). В теории это должно работать (немного) быстрее.РЕДАКТИРОВАТЬ : Спасибо @Dave. Мой редактор контролировал меня. Я думал, что использую вкладки, но вместо этого он конвертируется в 4 пробела. Также изучил практически все советы по Python и применил их.
РЕДАКТИРОВАТЬ : Переключен на 0-индексирование, позволяет мне сохранить пару байтов с генерацией простых чисел. Также переосмыслил пару сравнений
РЕДАКТИРОВАТЬ : Использовать переменную для хранения результатов тестов вместо
for/else
операторов.РЕДАКТИРОВАТЬ : переместил
lambda
внутрь функции, чтобы устранить необходимость в параметре.РЕДАКТИРОВАТЬ : преобразован в программу для сохранения байтов
РЕДАКТИРОВАТЬ : Python 2 экономит мне байты! Также мне не нужно конвертировать входные данные в
int
источник
a^(d*2^r) mod n
!Perl + Math :: Prime :: Util, 81 + 27 = 108 байт
Запуск с
-lpMMath::Prime::Util=:all
(штраф 27 байт, ой).объяснение
Это не просто Mathematica, которая имеет встроенную функцию для чего угодно. В Perl есть CPAN, одно из первых больших библиотечных хранилищ, в котором есть огромная коллекция готовых решений для таких задач, как эта. К сожалению, они не импортируются (или даже не устанавливаются) по умолчанию, а это означает, что использовать их в код-гольфе практически невозможно , но когда один из них идеально подходит для решения проблемы…
Мы пробегаем последовательные целые числа, пока не найдем то, которое не является простым, и все же сильным псевдопригодным для всех целочисленных оснований от 2 до n- го простого числа. Опция командной строки импортирует библиотеку, содержащую рассматриваемые встроенные функции, а также задает неявный ввод (для строки за раз;
Math::Prime::Util
имеет собственную встроенную библиотеку bignum, которая не любит переводы строк в свои целые числа). При этом$\
в качестве переменной используется стандартный прием Perl (разделитель выходных строк) в качестве переменной, чтобы уменьшить неуклюжие разборы и позволить неявно генерировать выходные данные.Обратите внимание, что нам нужно использовать
is_provable_prime
здесь, чтобы запросить детерминированный, а не вероятностный, простой тест. (Особенно с учетом того, что вероятностный простой тест, скорее всего, использует Миллера-Рабина, что в этом случае не может дать надежных результатов!)Perl + Math :: Prime :: Util, 71 + 17 = 88 байт, в сотрудничестве с @Dada
Выполнить с
-lpMntheory=:all
(штраф 17 байт).При этом используются несколько уловок игры в гольф на Perl, о которых я либо не знал (по-видимому, у Math :: Prime :: Util есть аббревиатура!), О которых знал, но не думал об использовании (
}{
чтобы выводить$\
неявно один раз, а не"$_$\"
неявно каждую строку) или знал, но каким-то образом сумел неправильно (удалив скобки из вызовов функций). Спасибо @Dada за указание на это. Кроме того, он идентичен.источник
ntheory
вместоMath::Prime::Util
. Кроме того,}{
вместо;$_=""
должно быть хорошо. И вы можете опустить пробел после1
и скобки нескольких вызовов функций. Также&
работает вместо&&
. Это должно дать 88 байт:perl -Mntheory=:all -lpe '1until!is_provable_prime(++$\)&is_strong_pseudoprime$\,2..nth_prime$_}{'
}{
. (Как ни странно, я вспомнил про скобки, но я давно играл в гольф на Perl и не мог вспомнить правила его пропуска.)ntheory
Хотя я совсем не знал об аббревиатуре.