A tarefa é a seguinte: Dado um número inteiro positivo x
e um prime n > x
, produz o menor número inteiro positivo y
tal que (y * y) mod n = x
. Uma parte importante desta questão é o prazo especificado abaixo, que exclui as soluções de força bruta.
Se não houver esse valor y
, seu código deverá ser exibido N
.
Casos de teste
(2, 5, N),
(3, 5, N),
(4, 5, 2),
(524291, 1048583, N),
(529533, 1048583, N),
(534775, 1048583, 436853),
(540017, 1048583, 73675),
(536870913, 1073741827, 375394238),
(542239622, 1073741827, 267746399),
(547608331, 1073741827, N),
(552977040, 1073741827, 104595351),
(1099511627676, 1099511627791, N),
(1099511627677, 1099511627791, 269691261521),
(1099511627678, 1099511627791, 413834069585),
(1267650600228229401496703204376, 1267650600228229401496703205653, 5312823546347991512233563776),
(1267650600228229401496703204476, 1267650600228229401496703205653, N)
(1267650600228229401496703204576, 1267650600228229401496703205653, N)
(1267650600228229401496703204676, 1267650600228229401496703205653, 79905476259539917812907012931)
Entrada e saída
Você pode receber e fornecer resultados da maneira que for conveniente. Se você não gostar da saída N
, qualquer Falsey
valor será suficiente .
Restrições
Seu código deve responder a todos os casos de teste em menos de 1 minuto em uma área de trabalho padrão. Esse prazo é apenas para evitar respostas de força bruta e espero que boas respostas sejam executadas quase instantaneamente. Você não pode usar nenhuma biblioteca ou componente interno que resolva esse problema ou que teste se um número é um resíduo quadrático.
1267650600228229401496703205653
si mesmo ou se possui suporte de 128 bits, como__int128
no gcc. Há também várias bibliotecas int de 256 bits disponíveis para vários idiomas. Por fim, muitos idiomas têm uma biblioteca int de precisão arbitrária.Respostas:
Pitão,
8382 bytesSuíte de teste
Este programa implementa o algoritmo Tonelli-Shanks . Eu escrevi seguindo de perto a página da Wikipedia. Toma como entrada
(n, p)
.A ausência de uma raiz quadrada é relatada pelo seguinte erro:
Este é um código muito complexo, escrito no estilo imperativo, em oposição ao estilo funcional mais comum de Pyth.
O único aspecto sutil do Pyth que estou usando é o
=
qual, se não for imediatamente seguido por uma variável, pesquisa no futuro a próxima variável no programa, atribui o resultado da expressão a seguir a essa variável e retorna esse resultado. Vou me referir em toda a explicação à página da wikipedia: algoritmo Tonelli-Shanks , pois esse é o algoritmo que estou implementando.Explicação:
A
pega uma tupla de 2 como entrada e atribui os valores aG
eH
respectivamente, e retorna sua entrada.Q
é a entrada inicial.e
retorna o último elemento de uma sequência. Após esse trecho,G
én
eH
eQ
ép
.M
define uma função de 2 entradasg
, onde as entradas sãoG
eH
..^
é a rápida função de exponenciação modular de Pyth. Esse snippet defineg
como significando mod de exponenciaçãoQ
.f
define um loop de repetição até falso e retorna o número de iterações para as quais é executado, fornecido1
como sua entrada. Durante cada iteração do loop, dividimosH
por 2, configuramosH
para esse valor e verificamos se o resultado é ímpar. Uma vez que paramos.K
armazena o número de iterações realizadas.Uma coisa muito complicada é a parte
=2;
.=
procura a próxima variável, que éT
, então,T
é definida como 2. No entanto,T
dentro de umf
loop está o contador de iterações, então usamos;
para obter o valor doT
ambiente global. Isso é feito para salvar alguns bytes de espaço em branco que seriam necessários para separar os números.Após esse trecho,
K
éS
do artigo da wikipedia (wiki) eH
éQ
do wiki, eT
é2
.Agora, precisamos encontrar um mod quadrático sem resíduo
p
. Forçaremos isso usando o critério de Euler./Q2
é(p-1)/2
, uma vez que/
é a divisão com piso,ftgT/Q;1
encontra o primeiro número inteiroT
ondeT ^ ((p-1)/2) != 1
, conforme desejado. Lembre-se de que;
extrai novamenteT
do ambiente global, que ainda é 2. Esse resultado éz
do wiki.Em seguida, para criar a
c
partir do wiki, precisamosz^Q
, então envolvemos o item acimag ... H
e atribuímos o resultado aT
. AgoraT
éc
do wiki.Vamos separar o seguinte:
~gGH
.~
é como=
, mas retorna o valor original da variável, não seu novo valor. Assim, ele retornaG
, que én
do wiki.Isso atribui
J
o valor den^((Q+1)/2)
, que éR
do wiki.Agora, o seguinte entra em vigor:
Isso atribui
G
o valorn^Q
, que ét
do wiki.Agora, temos nossas variáveis de loop configuradas.
M, c, t, R
do wiki sãoK, T, G, J
.O corpo do loop é complicado, então eu vou apresentá-lo com o espaço em branco, da maneira que escrevi:
Primeiro, verificamos se
G
é 1. Se sim, saímos do loop.O próximo código que é executado é:
Aqui, procuramos o primeiro valor de
i
tal modo queG^(2^i) mod Q = 1
, começando em 1. O resultado é salvo emK
.Aqui, pegamos o valor antigo de
K
, subtraímos o novo valor deK
, subtraímos 1, aumentamos 2 para esse poder e depois aumentamosT
para esse mod de poderQ
e depois atribuímos o resultado aT
. Isso tornaT
igual aob
do wiki.Essa também é a linha que encerra o loop e falha se não houver solução, porque nesse caso o novo valor de
K
será igual ao antigo valor deK
2 será aumentado para-1
e a exponenciação modular gerará um erro.Em seguida, multiplicamos
J
pelo resultado acima e o armazenamos novamenteJ
, mantendo-oR
atualizado.Em seguida, agrupamos
T
e armazenamos o resultado novamenteT
,T
retornando aoc
wiki.Então multiplicamos
G
por esse resultado, pegamos o modQ
e armazenamos o resultado novamenteG
.E encerramos o loop.
Depois que o loop termina,
J
existe uma raiz quadrada den
modp
. Para encontrar o menor, usamos o seguinte código:_BJ
cria a listaJ
e sua negação,%
assume implicitamenteQ
como seu segundo argumento e usa o comportamento padrão de Pyth para aplicar% ... Q
a cada membro da sequência. Em seguida,S
classifica a lista eh
leva seu primeiro membro, o mínimo.fonte
Python 2, 166 bytes
fonte
%timeit Q(1267650600228229401496703204676,1267650600228229401496703205653) 100 loops, best of 3: 2.83 ms per loop
:)SageMath , 93 bytes
Reduzindo a um problema muito mais difícil, para o qual o SageMath possui recursos internos suficientemente rápidos.
Experimente no SageMathCell
fonte
Haskell , 326 bytes
Normalmente, eu gosto de respostas de força bruta. Como isso é fortemente desencorajado pelo prazo, aqui está a maneira mais eficiente que eu conheço:
Experimente online!
Tenho certeza de que isso pode ser melhorado, mas isso deve ser feito por enquanto.
fonte
testCases
os do TIO original, que mal cabem em um comentário, mesmo sem eles.testCases
.