Uma fórmula para Parabéns

10

O teorema chinês do restante pode ser bastante útil na aritmética modular.

Por exemplo, considere o seguinte conjunto de relações de congruência:

Conjunto de congruência

Para conjuntos de relações de congruência como essa, em que todas as bases ( 3, 5, 7neste exemplo) são co-primas entre si, haverá um e apenas um número inteiro nentre 1e o produto das bases ( 3*5*7 = 105neste exemplo) inclusive, que satisfaz as relações .

Neste exemplo, o número seria 14, gerado por esta fórmula:

Fórmula

onde 2, 4, and 0são fornecidos a partir do exemplo acima.

70, 21, 15são os coeficientes da fórmula e são dependentes das bases 3, 5, 7,.

Para calcular os coeficientes da fórmula ( 70, 21, 15em nosso exemplo) para um conjunto de bases, usamos o seguinte procedimento.

Para cada número aem um conjunto de bases:

  1. Encontre o produto de todas as outras bases, denotadas como P.
  2. Encontre o primeiro múltiplo Pque deixa um resto de 1quando dividido por a. Este é o coeficiente de a.

Por exemplo, para calcular o coeficiente que corresponde à base 3, encontramos o produto de todas as outras bases (ie 5*7 = 35) e, em seguida, encontramos o primeiro múltiplo desse produto que deixa um restante 1quando dividido pela base.

Nesse caso, 35deixa o restante de 2quando dividido por 3, mas 35*2 = 70deixa o restante de 1quando dividido por 3, assim 70como o coeficiente correspondente para 3. Da mesma forma, 3*7 = 21deixa o restante de 1quando dividido por 5e 3*5 = 15deixa o restante de 1quando dividido por 7.

Em poucas palavras

Para cada número aem um conjunto de números:

  1. Encontre o produto de todos os outros números, denotados como P.
  2. Encontre o primeiro múltiplo Pque deixa um resto de 1quando dividido por a. Este é o coeficiente de a.

O desafio

  • O desafio é, para um conjunto de duas ou mais bases, encontrar o conjunto dos coeficientes correspondentes.
  • É garantido que o conjunto de bases seja co-prime em pares e cada base seja maior que 1.
  • Sua entrada é uma lista de números inteiros como entrada [3,4,5]ou sequência separada por espaço "3 4 5"ou, no entanto, suas entradas funcionam.
  • Sua saída deve ser uma lista de números inteiros ou sequência separada por espaço que denota o conjunto de coeficientes.

Casos de teste

input             output
[3,5,7]           [70,21,15]
[2,3,5]           [15,10,6]
[3,4,5]           [40,45,36]
[3,4]             [4,9]
[2,3,5,7]         [105,70,126,120]
[40,27,11]        [9801,7480,6480]
[100,27,31]       [61101,49600,56700]
[16,27,25,49,11]  [363825,2371600,2794176,5583600,529200]

Muito obrigado a Leaky Nun por sua ajuda ao escrever este desafio. Como sempre, se o problema não estiver claro, entre em contato. Boa sorte e bom golfe!

Sherlock9
fonte
Sempre haverá 3 números na entrada?
Xnor
@xnor Nope. Casos de teste editados.
Sherlock9

Respostas:

5

Haskell, 61 55 53 bytes

f x=[[p|p<-[0,product x`div`n..],p`mod`n==1]!!0|n<-x]

Define uma função fque recebe entrada e fornece saída como uma lista de números inteiros.

f x=[                                          |n<-x]  (1)
              product x                                (2)
                       `div`n                          (3)

Primeiro fazemos um loop sobre todos os números inteiros na entrada (1). Depois, pegamos o produto de todos os números inteiros (2) e dividimos por n para obter apenas o produto dos não ninteiros, que é P(3).

           [0,               ..]                       (4)
     [p|p<-                     ,p`mod`n==1]           (5)
                                            !!0        (6)

Em seguida, usamos o resultado ( P) como o valor da etapa para um intervalo que começa em zero (4). Nós pegamos o resultado [0, P, 2P, 3P, ...]e filtramos em valores para os quais o resultado de uma operação mod-n é um (5). Por fim, tomamos o primeiro elemento, que funciona graças à avaliação preguiçosa (6).

Obrigado a @xnor por 2 bytes!

Maçaneta da porta
fonte
11
Bem-vindo ao haskell! Eu acho que você quotpode ser um div, e headpode ser !!0.
Xnor
4

Jelly , 11 7 bytes

P:*ÆṪ%P

Experimente online! ou verifique todos os casos de teste .

fundo

Seja P e um estritamente positivos, números coprime .

O processo de duas etapas da pergunta - encontrar um múltiplo de P que deixa um restante de 1 quando dividido por um - pode ser descrito pela seguinte equação de congruência.

equação de congruência linear

Pelo teorema de Euler-Fermat , temos

Teorema de Euler-Fermat

onde φ denota a função totiente de Euler . Deste resultado, deduzimos o seguinte.

fórmula para a equação da congruência linear

Finalmente, como o desafio exige que calculemos Px , observamos que

fórmula para resultado final

Onde Pa pode ser calculado como o produto de todos os módulos.

Como funciona

P:*ÆṪ%P  Main link. Argument: A (list of moduli)

P        Yield the product of all moduli.
 :       Divide the product by each modulus in A.
   ÆṪ    Apply Euler's totient function to each modulus.
  *      Raise each quotient to the totient of its denominator.
     %P  Compute the remainder of the powers and the product of all moduli.
Dennis
fonte
2

J, 13 bytes

*/|5&p:^~*/%]

Baseado na incrível resposta de @Dennis .

Uso

Alguns casos de teste precisarão da entrada como números inteiros estendidos que possuem um sufixo x.

   f =: */|5&p:^~*/%]
   f 3 5 7
70 21 15
   f 40x 27 11
9801 7480 6480
   f 16x 27 25 49 11
363825 2371600 2794176 5583600 529200

Explicação

*/|5&p:^~*/%]  Input: list B
         */    Reduce B using multiplication to get the product of the values
            ]  Identity function, get B
           %   Divide the product by each value in B, call the result M
   5&p:        Apply the totient function to each value in B, call the result P
       ^~      Raise each value in M to the power of its corresponding value in P
*/             The product of the values in B
  |            Compute each power modulo the product and return

Experimente aqui.

milhas
fonte
2

Mathematica, 27 bytes

PowerMod[a=LCM@@#/#,-1,#]a&
alefalpha
fonte
1

Geléia, 14 13 bytes

P:×"Ḷð%"’¬æ.ḷ

Guardou um byte graças a @ Dennis !

Usa o processo descrito na especificação do desafio. A entrada é uma lista de bases e a saída é uma lista de coeficientes.

Experimente online ou verifique todos os casos de teste .

Explicação

P:×"Ḷð%"’¬æ.ḷ  Input: a list B
P              Get the product of the list
 :             Divide it by each value in the B, call it M
    Ḷ          Get a range from 0 to k for k in B
  ×"           Vectorized multiply, find the multiples of each M
     ð         Start a new dyadic chain. Input: multiples of M and B
      %"       Vectorized modulo, find the remainders of each multiple by B
        ’      Decrement every value
               If the remainder was 1, decrementing would make it 0
         ¬     Logical NOT, zeros become one and everything else becomes 0
            ḷ  Get the multiples of M
          æ.   Find the dot product between the modified remainders and the multiples
               Return
milhas
fonte
1

JavaScript (ES6), 80 bytes

a.map(e=>[...Array(e).keys()].find(i=>p*i/e%e==1)*p/e,p=a.reduce((i,j)=>i*j))

Eu tentei o algoritmo euclidiano estendido, mas são necessários 98 bytes:

a=>a.map(e=>(r(e,p/e)+e)%e*p/e,p=a.reduce((i,j)=>i*j),r=(a,b,o=0,l=1)=>b?r(b,a%b,t,o-l*(a/b|0)):o)

Se os valores forem todos primos, o ES7 poderá fazê-lo em 56 bytes:

a=>a.map(e=>(p/e%e)**(e-2)%e*p/e,p=a.reduce((i,j)=>i*j))
Neil
fonte
1

Python + SymPy, 71 bytes

from sympy import*
lambda x:[(prod(x)/n)**totient(n)%prod(x)for n in x]

Isso usa o algoritmo da minha resposta Jelly . A E / S está na forma de listas de números SymPy.

Dennis
fonte
1

Python 2, 87 84 bytes

Uma implementação simples do algoritmo. Sugestões de golfe são bem-vindas.

a=input();p=1
for i in a:p*=i
print[p/i*j for i in a for j in range(i)if p/i*j%i==1]
Sherlock9
fonte
Um programa completo salvaria 3 bytes.
Dennis
1

Queijo Cheddar , 64 bytes

n->n.map(i->(|>i).map(j->(k->k%i>1?0:k)(n.reduce((*))/i*j)).sum)
Freira Furada
fonte
Devo acrescentar um .productque faz .reduce((*))para arrays ...
Downgoat
0

GAP = VÃO , 51 bytes

O GAP possui uma função que pode calcular o exemplo motivador ChineseRem([2,5,7],[2,4,0]), mas que ainda não facilita a obtenção dos coeficientes. Podemos obter o n-ésimo coeficiente usando a lista com um na n-ésima posição e zeros nas outras posições como segundo argumento. Portanto, precisamos criar essas listas e aplicar a função a todas elas:

l->List(Basis(Integers^Size(l)),b->ChineseRem(l,b))
Peneiradores cristãos
fonte
0

Lote, 148 bytes

@set p=%*
@set/ap=%p: =*%
@for %%e in (%*)do @for /l %%i in (1,1,%%e)do @call:l %%e %%i
@exit/b
:l
@set/an=p/%1*%2,r=n%%%1
@if %r%==1 echo %n%
Neil
fonte
0

Na verdade, 14 bytes

Isso usa o algoritmo na resposta de Dennis Jelly . Outra resposta baseada na minha resposta em Python é futura. Sugestões de golfe são bem-vindas. Experimente online!

;π;)♀\;♂▒@♀ⁿ♀%

Como funciona

                 Implicit input a.
;                Duplicate a.
 π;)             Take product() of a, duplicate and rotate to bottom.
    ♀\           Integer divide the product by each element of a. Call this list b.
      ;♂▒        Take that list, duplicate, and get the totient of each element.
         @♀ⁿ     Swap and take pow(<item in b>, <corresponding totient>)
            ♀%   Modulo each item by the remaining duplicate product on the stack.
                 Implicit return.

Outra resposta baseada na minha resposta Python em 22 bytes. Sugestões de golfe são bem-vindas. Experimente online!

;π╖`╝╛╜\╛r*"╛@%1="£░`M

Como funciona

            Implicit input a.
;π╖         Duplicate, take product of a, and save to register 0.
`...`M      Map over a.
  ╝           Save the item, b, in register 1.
  ╛╜\         product(a) // b. Call it P.
  ╛r          Take the range [0...b].
  *           Multiply even item in the range by P. Call this list x.
  "..."£░     Turn a string into a function f.
              Push values of [b] where f returns a truthy value.
    ╛@%         Push b, swap, and push <item in x> % b.
    1=          Does <item> % b == 1?
            Implicit return.
Sherlock9
fonte