o Teorema Chinês do Restante nos diz que sempre podemos encontrar um número que produz quaisquer restos necessários sob diferentes módulos primos. Seu objetivo é escrever código para gerar esse número em tempo polinomial. O menor código vence.
Por exemplo, digamos que recebemos essas restrições ( %
representa mod):
n % 7 == 2
n % 5 == 4
n % 11 == 0
Uma solução é n=44
. A primeira restrição é satisfeita porque 44 = 6*7 + 2
, e assim 44
tem o restante 2
quando dividido por 7
, e assim 44 % 7 == 2
. As outras duas restrições também são atendidas. Existem outras soluções, como n=814
e n=-341
.
Entrada
Uma lista não vazia de pares (p_i,a_i)
, em que cada módulo p_i
é um primo distinto e cada destino a_i
é um número natural no intervalo 0 <= a_i < p_i
. Você pode receber informações da forma que for mais conveniente; não precisa ser realmente uma lista de pares. Você não pode assumir que a entrada está classificada.
Saída
Um número inteiro n
tal que n % p_i == a_i
para cada índice i
. Ele não precisa ser o menor valor possível e pode ser negativo.
Restrição de tempo polinomial
Para evitar soluções baratas que apenas tentar n=0
, n=1
, n=2
, e assim por diante, seu código deve ser executado em tempo polinomial no comprimento da entrada . Observe que um número m
na entrada possui comprimento Θ(log m)
; portanto, m
ele não é polinomial em seu comprimento. Isso significa que você não pode contar até m
ou executar um m
tempo de operação , mas pode calcular operações aritméticas nos valores.
Você não pode usar um formato de entrada ineficiente como unário para contornar isso.
Outras proibições
Não são permitidos embutidos para fazer o seguinte: Implemente o teorema chinês Remainder, resolva equações ou números de fatores.
Você pode usar built-ins para encontrar mods e fazer adição, subtração, multiplicação e exponenciação modulares (com expoente de número natural). Você não pode usar outras operações modulares integradas, incluindo inversa modular, divisão e busca de pedidos.
Casos de teste
Estes fornecem a menor solução não negativa. Sua resposta pode ser diferente. Provavelmente é melhor se você verificar diretamente se sua saída satisfaz cada restrição.
[(5, 3)]
3
[(7, 2), (5, 4), (11, 0)]
44
[(5, 1), (73, 4), (59, 30), (701, 53), (139, 112)]
1770977011
[(982451653, 778102454), (452930477, 133039003)]
68121500720666070
Respostas:
Mathematica,
555145O inverso modular é proibido, mas a exponenciação modular é permitida. Pelo pequeno teorema de Fermat
n^(-1) % p == n^(p-2) % p
,.Exemplo:
Apenas por diversão:
fonte
PowerMod[#2,#-2,#]
e também não acho que exista um requisito para que a função seja nomeada, reduzindo-a para 48.Python 2,
165101999885 bytesUsando o pequeno teorema de Fermat como as outras respostas. Não se preocupa em manter a soma final dentro da faixa modular, pois não estamos interessados na menor solução. Obrigado Volatility por salvar 13 bytes.
fonte
for
.x/a*b*pow(x/a,a-2,a)for a,b in l
Deveria trabalhar.Pitão,
40373629Usa o pequeno teorema de Fermat, graças aos alefalpha. Calcula usando esta fórmula .
fonte
Ruby, 129
Bem, camaradas, parece que as soluções Ruby precisam ser mais longas porque a exponenciação modular não está disponível sem carregar a biblioteca openssl e fazer conversões no OpenSSL :: BN. Ainda assim, me diverti escrevendo:
fonte
require
,eval
ouputs
.Python 2, 61
Isso emprega uma variação da construção do produto que outras respostas usam.
A idéia é fazer um loop sobre as restrições e atualizar a solução
n
para atender à restrição atual sem atrapalhar as anteriores. Para fazer isso, rastreamos o produtoP
dos primos vistos até agora e observamos que a adição de um múltiplo deP
não tem efeito modulo a qualquer primo já visto.Portanto, precisamos mudar
n
para satisfazern%p == a
adicionando o múltiplo certo deP
. Resolvemos o coeficientec
:(n + P*c) % p == a
Isso requer que
c = (a-n) * P^(-1)
, onde o inverso é tomado módulop
. Como outros observam, o inverso pode ser calculado pelo Pequeno Teorema de Fermat comoP^(-1) = pow(P,p-2,p)
. Então,,c = (a-n) * pow(P,p-2,p)
e nós atualizamosn
porn+= P * (a-n) * pow(P,p-2,p)
.fonte
Haskell,
68100 bytesUso:
f [(5,1), (73,4), (59,30), (701,53), (139,112)]
->142360350966
.Edit: agora com uma função rápida "power / mod". Versão antiga (68 bytes) com função de energia embutida:
fonte