Dado um número inteiro não negativo N
, imprima o menor número inteiro positivo ímpar que é um forte pseudoprime para todas as primeiras N
bases primárias.
Esta é a sequência O0IS A014233 .
Casos de teste (um indexado)
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
Os casos de teste para N > 13
não estão disponíveis porque esses valores ainda não foram encontrados. Se você conseguir encontrar o (s) próximo (s) termo (s) na sequência, certifique-se de enviá-lo à OEIS!
Regras
- Você pode optar por usar
N
como um valor indexado a zero ou um indexado. - É aceitável que sua solução funcione apenas para os valores representáveis no intervalo inteiro do seu idioma (até
N = 12
números inteiros de 64 bits não assinados), mas sua solução deve teoricamente funcionar para qualquer entrada, supondo que seu idioma suporte números inteiros de comprimento arbitrário.
fundo
Qualquer inteiro par positivo x
pode ser escrito na forma x = d*2^s
em que d
é estranho. d
e s
pode ser calculado dividindo repetidamente n
por 2 até que o quociente não seja mais divisível por 2. d
é esse quociente final e s
é o número de vezes que 2 divide n
.
Se um número inteiro positivo n
é primo, o pequeno teorema de Fermat declara:
Em qualquer campo finito Z/pZ
(onde p
é primo), as únicas raízes quadradas de 1
são 1
e -1
(ou, equivalentemente 1
e p-1
).
Podemos usar esses três fatos para provar que uma das duas declarações a seguir deve ser verdadeira para um primo n
(onde d*2^s = n-1
e r
é um número inteiro [0, s)
):
O teste de primalidade de Miller-Rabin opera testando o contrapositivo da reivindicação acima: se existe uma base a
tal que ambas as condições acima sejam falsas, então n
não é primo. Essa base a
é chamada de testemunha .
Agora, testar todas as bases [1, n)
seria proibitivamente caro em tempo de computação para grandes empresas n
. Existe uma variante probabilística do teste de Miller-Rabin que apenas testa algumas bases escolhidas aleatoriamente no campo finito. No entanto, foi descoberto que testar apenas a
bases primárias é suficiente e, portanto, o teste pode ser realizado de maneira eficiente e determinística. De fato, nem todas as bases principais precisam ser testadas - apenas um certo número é necessário, e esse número depende do tamanho do valor que está sendo testado para a primalidade.
Se um número insuficiente de bases primárias for testado, o teste poderá produzir falsos positivos - números inteiros compostos ímpares em que o teste falha em provar sua composição. Especificamente, se uma base a
falhar em provar a composição de um número composto ímpar, esse número será chamado de forte pseudo-tempo para a base a
. Esse desafio consiste em encontrar os números compostos ímpares que são psuedoprimes fortes para todas as bases menores ou iguais ao N
número primo (o que equivale a dizer que eles são pseudoprimes fortes para todas as bases primárias menores ou iguais ao N
número primo) .
Respostas:
C,
349295277267255 bytesRecebe entrada baseada em 1 no stdin, por exemplo:
Certamente não descobrirá novos valores na sequência tão cedo, mas faz o trabalho. ATUALIZAÇÃO: agora ainda mais lenta!
a^(d*2^r) == (a^d)^(2^r)
)__int128
, que é mais curto do queunsigned long long
enquanto trabalha com números maiores! Também em máquinas little-endian, o printf with%llu
ainda funciona bem.Menos minificado
Composição (desatualizada)
Como mencionado, isso usa entrada baseada em 1.
Mas para n = 0, produz 9, que segue a sequência relacionada https://oeis.org/A006945 .Não mais; agora ele fica no 0.Deve funcionar para todos os n (pelo menos até a saída atingir 2 ^ 64), mas é incrivelmente lento. Eu verifiquei em n = 0, n = 1 e (depois de muita espera), n = 2.
fonte
Python 2,
633465435292282275256247 bytesIndexado a 0
A conversão de uma função para um programa salva alguns bytes de alguma forma ...
Se o Python 2 me fornecer uma maneira mais curta de fazer a mesma coisa, vou usar o Python 2. A divisão é por padrão um número inteiro, portanto, é uma maneira mais fácil de dividir por 2 e
print
não precisa de parênteses.Experimente online!
O Python é notoriamente lento em comparação com outros idiomas.
Define um teste de divisão de teste para correção absoluta e aplica repetidamente o teste de Miller-Rabin até que um pseudoprime seja encontrado.
Experimente online!
EDIT : Finalmente jogou a resposta
EDIT : Usado
min
para o teste de primalidade da divisão de teste e alterado para alambda
. Menos eficiente, mas mais curto. Também não pude evitar e usei alguns operadores bit a bit (sem diferença de comprimento). Em teoria, deve funcionar (um pouco) mais rápido.EDIT : Obrigado @Dave. Meu editor me trollou. Eu pensei que estava usando guias, mas estava sendo convertido em 4 espaços. Também passou por praticamente todas as dicas de Python e a aplicou.
EDIT : Comutado para indexação 0, permite-me salvar alguns bytes com a geração dos números primos. Também repensou algumas comparações
EDIT : Usou uma variável para armazenar o resultado dos testes em vez de
for/else
instruções.EDIT : Moveu a parte
lambda
interna da função para eliminar a necessidade de um parâmetro.EDIT : convertido em um programa para salvar bytes
EDIT : Python 2 me salva bytes! Também não tenho que converter a entrada para
int
fonte
a^(d*2^r) mod n
!Perl + Math :: Prime :: Util, 81 + 27 = 108 bytes
Corra com
-lpMMath::Prime::Util=:all
(penalidade de 27 bytes, ai).Explicação
Não é apenas o Mathematica que tem um construído para basicamente qualquer coisa. O Perl possui o CPAN, um dos primeiros grandes repositórios de bibliotecas, e que possui uma enorme coleção de soluções prontas para tarefas como esta. Infelizmente, eles não são importados (ou mesmo instalados) por padrão, o que significa que basicamente nunca é uma boa opção usá-los no code-golf , mas quando um deles se encaixa perfeitamente no problema…
Corremos através inteiros consecutivos até encontrar um que não é nobre, e ainda um pseudoprimo forte para todas as bases inteiro de 2 a o n º prime. A opção de linha de comando importa a biblioteca que contém o interno em questão e também define a entrada implícita (para linha por vez;
Math::Prime::Util
possui sua própria biblioteca de bignum interna que não gosta de novas linhas em seus números inteiros). Isso usa o truque Perl padrão de usar$\
(separador de linha de saída) como uma variável, a fim de reduzir as análises estranhas e permitir que a saída seja gerada implicitamente.Observe que precisamos usar
is_provable_prime
aqui para solicitar um teste principal determinístico, e não probabilístico. (Especialmente considerando que um teste probabilístico de primeira ordem provavelmente usa Miller-Rabin em primeiro lugar, o que não podemos esperar fornecer resultados confiáveis neste caso!)Perl + Math :: Prime :: Util, 71 + 17 = 88 bytes, em colaboração com @Dada
Corra com
-lpMntheory=:all
(penalidade de 17 bytes).Isso usa alguns truques de golfe Perl que eu não conhecia (aparentemente Math :: Prime :: Util tem uma abreviação!), Conhecia, mas não pensava em usar (
}{
para gerar$\
implicitamente uma vez, em vez de"$_$\"
implicitamente todas as linhas) , ou sabia, mas de alguma forma conseguiu aplicar incorretamente (remover parênteses das chamadas de função). Agradeço a @Dada por me indicar isso. Além disso, é idêntico.fonte
ntheory
vez deMath::Prime::Util
. Além disso, em}{
vez de;$_=""
deve ficar bem. E você pode omitir o espaço após1
e o parêntese de algumas chamadas de função. Além disso,&
funciona em vez de&&
. Isso deve dar 88 bytes:perl -Mntheory=:all -lpe '1until!is_provable_prime(++$\)&is_strong_pseudoprime$\,2..nth_prime$_}{'
}{
. (Estranhamente, lembrei-me da coisa entre parênteses, mas já faz um tempo desde que jogava golfe em Perl e não conseguia lembrar as regras para deixá-la de fora.) No entanto, eu não sabia dantheory
abreviação.