Segundo plano (pule para definições)
Euler provou um belo teorema sobre os números complexos: e ix = cos (x) + i sin (x).
Isso facilita a prova do teorema de De Moivre:
(e ix ) n = e i (nx)
(cos (x) + i sen (x)) n = cos (nx) + i sen (nx)
Podemos plotar números complexos usando o plano euclidiano bidimensional, com o eixo horizontal representando a parte real e o eixo vertical representando a parte imaginária. Dessa forma, (3,4) corresponderia ao número complexo 3 + 4i.
Se você estiver familiarizado com as coordenadas polares, (3,4) seria (5, arctan (4/3)) nas coordenadas polares. O primeiro número, r, é a distância do ponto da origem; o segundo número, θ, é o ângulo medido do eixo x positivo ao ponto no sentido anti-horário. Como resultado, 3 = r cosθ e 4 = r sinθ. Portanto, podemos escrever 3 + 4i como r cosθ + ri sinθ = r (cosθ + i sinθ) = re iθ .
Vamos resolver a equação complexa z n = 1, onde n é um número inteiro positivo.
Deixamos z = re iθ . Então, z n = r n e inθ . A distância de z n da origem é r n , e o ângulo é nθ. No entanto, sabemos que a distância de 1 da origem é 1 e o ângulo é 0. Portanto, r n = 1 e nθ = 0. No entanto, se você girar mais 2π, ainda terminará no mesmo ponto, porque 2π é apenas um círculo completo. Portanto, r = 1 e nθ = 2kπ, dando-nos z = e 2ikπ / n .
Reafirmamos nossa descoberta: as soluções para z n = 1 são z = e 2ikπ / n .
Um polinômio pode ser expresso em termos de suas raízes. Por exemplo, as raízes de x 2 -3x + 2 são 1 e 2, então x 2 -3x + 2 = (x-1) (x-2). Da mesma forma, de nossa descoberta acima:
No entanto, esse produto certamente continha raízes de outros n. Por exemplo, considere n = 8. As raízes de z 4 = 1 também seriam incluídas nas raízes de z 8 = 1, uma vez que z 4 = 1 implica z 8 = (z 4 ) 2 = 1 2 = 1. Tome n = 6 como exemplo. Se z 2 = 1, também teríamos z 6 = 1. Da mesma forma, se z 3 = 1, então z 6 = 1.
Se quisermos extrair as raízes exclusivas de z n = 1, precisaríamos de k e n para não compartilhar nenhum divisor comum, exceto 1. Caso contrário, se eles compartilharem um divisor comum d, em que d> 1, z seria o (k / d) -ésima raiz de z n / d = 1. Usando a técnica acima para escrever o polinômio em termos de suas raízes, obtemos o polinômio:
Observe que esse polinômio é feito removendo as raízes de z n / d = 1, com d sendo um divisor de n. Afirmamos que o polinômio acima tem coeficientes inteiros. Considere o LCM dos polinômios na forma de z n / d -1, em que d> 1 ed divide n. As raízes do LCM são exatamente as que queremos remover. Como cada componente possui coeficientes inteiros, o LCM também possui coeficientes inteiros. Como o LCM divide z n -1, o quociente deve ser um polinômio com coeficiente inteiro, e o quociente é o polinômio acima.
As raízes de z n = 1 têm raio 1 e formam um círculo. O polinômio representa os pontos do círculo exclusivos de n; portanto, em certo sentido, os polinômios formam uma partição do círculo. Portanto, o polinômio acima é o n-ésimo polinômio ciclotômico. (ciclo- = círculo; tom- = cortar)
Definição 1
O n-ésimo polinômio ciclotômico, denotado , é o polinômio único com coeficientes inteiros que dividem x n -1, mas não x k -1 para k <n.
Definição 2
Os polinômios ciclotômicos são um conjunto de polinômios, um para cada número inteiro positivo, de modo que:
onde k | n significa k divide n.
Definição 3
O n-ésimo polinômio ciclotômico é o polinômio x n -1 dividido pelo LCM dos polinômios na forma x k -1 em que k divide n e k <n.
Exemplos
- Φ 1 (x) = x - 1
- Φ 2 (x) = x + 1
- Φ 3 (x) = x 2 + x + 1
- Φ 30 (x) = x 8 + x 7 - X 5 - X 4 - x 3 + x + 1
- Φ 105 (x) = x 48 + X 47 + x 46 - x 43 - x 42 - 2x 41 - x 40 - x 39 + X 36 + X 35 + X 34 + X 33 + X 32 + x 31 - x 28 - x 26 - x 24 - x 22 - x 20 + x 17 + x 16 + x 15 + x 14 + x 13 + x 12 - x9 - x 8 - 2x 7 - x 6 - x 5 + x 2 + x + 1
Tarefa
Dado um número inteiro positivo n
, retorne o n
-ésimo polinômio ciclotômico conforme definido acima, em um formato razoável (por exemplo, é permitida uma lista de coeficientes).
Regras
Você pode retornar números flutuantes / complexos, contanto que arredondem para o valor correto.
Pontuação
Isso é código-golfe . A resposta mais curta em bytes vence.
Referências
fonte
Respostas:
Haskell , 120 bytes
Experimente online!
Fornece uma lista de carros alegóricos complexos com entradas como
1.0000000000000078 :+ 3.314015728506092e-14
devido à imprecisão do carro alegórico. Um método direto de multiplicar para recuperar o polinômio de suas raízes.A
fromInteger
é uma grande concessão ao sistema de tipos da Haskell. Tem que haver uma maneira melhor. Sugestões são bem vindas. Lidar com raízes da unidade simbolicamente também pode funcionar.Haskell , 127 bytes
Experimente online!
Sem importações.
Usa a fórmula
Calcula Φ_n (x) dividindo o LHS por cada um dos outros termos no RHS.
O operador
%
faz divisão em polinômios, contando com o restante sendo zero. Supõe-se que o divisor seja monônico e é fornecido sem o 1 inicial, e também com zeros à direita infinitos para evitar truncamento ao fazerzipWith
.fonte
[0,0..]
é um byte menor querepeat 0
.Mathematica,
4341 bytesObviamente, sempre podemos usar o built-in, mas se não o fizermos, isso divide x n -1 por Φ k ( x ) (calculado recursivamente) para cada divisor adequado k de n .
Usamos
Factor
para obter um polinômio no final. Penso que a razão pela qual isso funciona é ox^#-1
fator de todos os polinômios ciclotômicos dos divisores de n , e então dividimos os que não queremos.-2 bytes graças a Jenny_mathy, reescrevendo
Factor
para aplicar somente ao numerador.fonte
Factor@
Factor[x^#-1]/Times@@...
vez disso; se não tivéssemos colchetes lá, gostaríamos de parênteses.Factor[x^#-1]/Times@@...
e também significa que não tenho idéia de como ele funciona.MATL ,
32312725 bytesA saída pode não ser um número inteiro devido a imprecisões de ponto flutuante (o que é permitido). O rodapé faz arredondamentos para maior clareza.
Experimente online!
fonte
Haskell ,
250 236 233 218216 bytesEsta é uma versão detalhada (o @xnor pode fazê-lo em quase metade da pontuação ), mas é garantido que funcione por
n
tanto tempo quanto você tiver memória suficiente, mas não usa um built-in para gerar o n-ésimo polinômio ciclotômico. A entrada é um número inteiro de tamanho arbitrário e a saída é do tipo polinomial com coeficientes racionais (exatos).A idéia aproximada aqui é calcular os polinômios recursivamente. Para
n=1
oun
prime, é trivial. Para todos os outros números, essa abordagem basicamente usa a fórmula da definição 2resolvido para . Obrigado @ H.PWiz por um monte de bytes!
Para
n=105
isso, obtém-se o seguinte polinômio (arrumei todos os%1
denominadores):O polinômio para
n=15015
pode ser encontrado aqui (o maior coeficiente é 23).Experimente online!
fonte
+1
por não ser um embutido.Rationals
? Parece funcionar bem sem elesquotRemPoly
, deixe-me tentar novamente!Double
coeficientes se você não usarRatio Integer
, o que pode causar problemas muito (muito) grandesn
.Gelatina , 23 bytes
Experimente online!
Saídas como uma lista de coeficientes.
Possui ponto flutuante E imprecisões complexas. O rodapé faz o arredondamento para tornar a saída mais bonita.
fonte
J , 36 bytes
Experimente online!
Usa a fórmula
Existem algumas imprecisões de ponto flutuante, mas isso é permitido.
fonte
Mathematica, 81 bytes
fonte
R ,
176171139112 bytesExperimente online!
Versão massivamente mais simples; usa um
for
loop em vez de aReduce
.fonte
Pari / GP , 8 bytes
Um embutido.
Experimente online!
Pari / GP , 39 bytes, sem built-in
Usando a fórmula:
Experimente online!
fonte
CJam (
5251 bytes)Demonstração online . Este é um bloco anônimo (função) que pega um número inteiro na pilha e deixa uma matriz big-endian de coeficientes na pilha.
Dissecação
fonte
JavaScript (ES6),
337333284...252250245242 bytesExplicação (selecionada):
Inicialize z = (1 + 0i) * x ^ 0
Cálculo GCD.
Como preciso usar bastante as funções de matemática, usei outra variável aqui.
Multiplicação polinomial.
A fórmula usada é
Comprima a saída de volta para uma matriz inteira.
Saídas:
Uma matriz de números inteiros, com o elemento na posição i representando o coeficiente de x ^ i.
Um dos problemas que JS tem é que, como o JS não fornece biblioteca nativa para cálculos em polinômios e números complexos, eles precisavam ser implementados de maneira semelhante a um array.
console.log (phi (105)) fornece
337> 333 (-4): foi alterado o código para verificar o valor indefinido
333> 284 (-49): alterada a função de multiplicação polinomial porque pode ser simplificada
284> 277 (-7): excluído algum código redundante
277> 265 (-12): use 2 variáveis em vez de uma matriz de 2 elementos para eliminar alguns bytes no uso da matriz
265> 264 (-1): use Array.push () em vez de Array.concat () para reduzir 4 bytes, mas adicionou 3 para as chaves de loop for e a variável z
264> 263 (-1): Mais golfe na última alteração
263> 262 (-1): jogou golfe no loop for
262> 260 (-2): aplicou a cláusula if
260> 258 (-2): combinação adicional das declarações
258> 252 (-6): Golfe na reutilização de referências de matriz
252> 250 (-2): Substitua alguns operadores unários como operadores binários
250> 245 (-5): mova o incremento em Array.map () para a última referência do contador para remover bytes
245> 242 (-3): use a sintaxe de propagação em vez de Array.push ()
fonte