사이클로 다항식


17

배경 (정의로 건너 뛰기)

오일러는 복소수에 대한 아름다운 정리를 증명했습니다 : e ix = cos (x) + i sin (x).

이것은 de Moivre의 정리를 쉽게 증명할 수있게합니다.

(e ix ) n = e i (nx)

(cos (x) + i sin (x)) n = cos (nx) + i sin (nx)

2 차원 유클리드 평면을 사용하여 복소수를 플로팅 할 수 있습니다. 가로축은 실수 부를 나타내고 세로축은 허수 부를 나타냅니다. 이런 식으로 (3,4)는 복소수 3 + 4i에 해당합니다.

극좌표에 익숙하면 극 좌표의 (3,4)는 (5, arctan (4/3))이됩니다. 첫 번째 숫자 r은 원점에서 점의 거리입니다. 두 번째 숫자 θ는 양의 x 축에서 지점까지 반 시계 방향으로 측정 된 각도입니다. 결과적으로 3 = r cosθ 및 4 = r sinθ입니다. 따라서 r cosθ + ri sinθ = r (cosθ + i sinθ) = re 로 3 + 4i를 쓸 수 있습니다 .

복소수 방정식 z n = 1을 풀고 , 여기서 n은 양의 정수입니다.

우리는 z = re 라고하자 . 그런 다음 z n = r n e inθ 입니다. 원점으로부터 z n 의 거리는 r n 이며 각도는 nθ입니다. 그러나 원점에서 1의 거리는 1이고 각도는 0입니다. 따라서 r n = 1이고 nθ = 0입니다. 그러나 2π 더 회전해도 2π는 완전한 원이므로 여전히 같은 지점에서 끝납니다. 따라서 r = 1이고 nθ = 2kπ이므로 z = e 2ikπ / n이 됩니다.

: 우리는 우리의 발견을 재 작성 Z에 솔루션을 N = 1, Z = 전자 있습니다 2ikπ / N .

다항식은 근으로 표현 될 수 있습니다. 예를 들어, x 2 -3x + 2 의 근 은 1과 2이므로 x 2 -3x + 2 = (x-1) (x-2)입니다. 마찬가지로 위의 발견에서 :

그러나 그 제품에는 확실히 다른 n의 뿌리가 들어있었습니다. 예를 들어, n = 8을 사용하십시오. z 4 = 1은 z 8 = (z 4 ) 2 = 1 2 = 1을 의미 하므로 z 4 = 1 의 근은 z 8 = 1 의 근 안에 포함됩니다 . z 2 = 1이면 z 6 = 1이됩니다. 마찬가지로 z 3 = 1이면 z 6 = 1입니다.

z n = 1에 고유 한 근을 추출하려면 1을 제외하고 공통 제수를 공유하지 않으려면 k와 n이 필요합니다. 그렇지 않으면 d> 1 인 공통 제수 d를 공유하면 z는 (k / d)-제곱근 z n / d = 1. 다항식을 근본으로 작성하기 위해 위의 기술을 사용하여 다항식을 얻습니다.

이 다항식은 z가 n 의 제수 인 z n / d = 1 의 근을 제거하여 수행됩니다 . 위의 다항식에는 정수 계수가 있다고 주장합니다. d> 1과 d는 n을 나누는 z n / d -1 형식의 다항식의 LCM을 고려하십시오 . LCM의 뿌리는 우리가 제거하고자하는 뿌리입니다. 각 성분에는 정수 계수가 있으므로 LCM에도 정수 계수가 있습니다. LCM이 z n -1을 나누므로 몫은 정수 계수의 다항식이어야하며 몫은 위의 다항식입니다.

z n = 1 의 근은 모두 반지름 1이므로 원을 형성합니다. 다항식은 n에 고유 한 원의 점을 나타내므로, 다항식은 원의 파티션을 형성합니다. 따라서, 상기 다항식은 n 번째 사이클로 다항식이다. (cyclo- = circle; tom- = 잘라 내기)

정의 1

으로 표시되는 n 번째 사이클로 다항식 은 k <n에 대해 x k -1이 아니라 x n -1 을 나누는 정수 계수를 갖는 고유 다항식 이다.

정의 2

사이클로 톰 다항식은 각 양의 정수마다 하나씩 다항식의 집합입니다.

어디서 k | n은 k가 n을 나누는 것을 의미합니다.

정의 3

n 번째 사이클로 다항식은 다항식 x n -1을 다항식 의 LCM으로 나눈 x k -1 형식 으로 k는 n과 k <n을 나눈다.

  1. Φ 1 (x) = x-1
  2. Φ 2 (x) = x + 1
  3. Φ 3 (x) = x 2 + x + 1
  4. Φ 30 (x) = x 8 + x 7 -x 5 -x 4 -x 3 + x + 1
  5. Φ 105 (X) = X (48) + X (47) + X (46) - X (43) - X (42) - 2 × (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 - 2 × 7 - X 6 - X 5 + X 2 + X + 1

직무

양수 주어 n리턴 n번째 cyclotomic 다항식 적당한 형식으로 상기 정의 된 바와 같은 (계수 ieeg 목록이 허용된다).

규칙

부동 소수점 / 복소수는 올바른 값으로 반올림되는 한 반환 할 수 있습니다.

채점

이것은 입니다. 바이트 단위의 최단 답변이 이깁니다.

참고 문헌


1
테스트에 105를 추가 하시겠습니까?
Jonathan Allan

@JonathanAllan 저는 48 개의 단어를 입력하고 싶지 않습니다
Leaky Nun

1
부동 소수점 부정확성이 허용됩니까?
마일

3
@miles 나는 열정으로 수레를 싫어한다.>. <그러나 나는 수레를 사용할 권리를 죽음에 방어 할 것이다.
Leaky Nun

1
가장 가까운 정수 / 가우시안 정수로 반올림 할 때 정답을 얻는 한 복잡한 부동 소수점 숫자를 출력 할 수 있습니까?
fireflame241241.

답변:


12

하스켈 , 120 바이트

import Data.Complex
p%a=zipWith(\x y->x-a*y)(p++[0])$0:p
f n=foldl(%)[1][cis(2*pi/fromInteger n)^^k|k<-[1..n],gcd n k<2]

온라인으로 사용해보십시오!

1.0000000000000078 :+ 3.314015728506092e-14float 부정확성으로 인해 같은 항목이있는 복잡한 float 목록을 제공합니다 . 뿌리에서 다항식을 복구하기 위해 곱하는 직접 방법.

이것은 fromInteger하스켈 타입 시스템에 큰 양보입니다. 더 좋은 방법이 있어야합니다. 제안은 환영합니다. 통일의 뿌리를 다루는 것도 상징적으로 작용할 수 있습니다.


하스켈 , 127 바이트

(h:t)%q|all(==0)t=[]|1>0=h:zipWith(\x y->x-h*y)t q%q
f n=foldl(%)(1:(0<$[2..n])++[-1])[tail$f k++[0,0..]|k<-[1..n-1],mod n k<1]

온라인으로 사용해보십시오!

수입품이 없습니다.

공식을 사용합니다

LHS를 RHS의 다른 각 항으로 나누어 Φ_n (x)를 계산합니다.

연산자 %는 다항식으로 나누고 나머지는 0입니다. 제수는 모닉 인 것으로 가정하고 선행 1없이 제공되며을 수행 할 때 잘림을 피하기 위해 무한 후행 0도 제공됩니다 zipWith.


[0,0..]보다 짧은 바이트 repeat 0입니다.
Laikoni

@flawr 다항식을 나눕니다. 귀하의 솔루션과 동일한 방법이라고 생각합니다.
xnor


이 답변을 통해 하스켈을 배우고 싶습니다.
주세페


7

매스 매 티카, 43 41 바이트

Factor[x^#-1]/Times@@#0/@Most@Divisors@#&

물론, 우리는 항상 내장 사용할 수 있지만, 우리가하지 않으면,이 분할은 X N -1 Φ에 의해 K ( X (재귀 적으로 계산)) 모든 적절한 제수에 대한 KN .

우리 Factor는 마지막에 다항식을 얻는 데 사용 합니다. 이것이 효과가있는 이유 x^#-1n 제수의 모든 순환 다항식에 요소를 곱한 다음 원치 않는 것을 나누는 것입니다.

Jenny_mathy 덕분에 -2 바이트 Factor는 분자에만 적용되도록 다시 씁니다 .


2
대단해! 다음을 사용하여 바이트를 저장할 수 있습니다.Factor@
J42161217

@Jenny_mathy Factor[x^#-1]/Times@@...대신 해석하는 것 같습니다 . 괄호가 없으면 괄호가 필요합니다.
Misha Lavrov

1
알았어 ..하지만 테스트 할 때 올바른 결과를 제공하고 있다고 말해야한다.
J42161217

그 흥미 롭군요. 그것은 우리가 그것을 작성하여 다른 바이트를 절약 할 수 있음을 의미 Factor[x^#-1]/Times@@...하며, 그것이 어떻게 작동하는지 전혀 알지 못합니다.
Misha Lavrov


4

하스켈 , 250 236 233 218 216 바이트

이것은 (@xnor 거의 그것을 할 수있는, 버전 장황 절반 점수 ) 그러나 그것은 어떤을위한 작업에 보장되는 n만큼 당신이 충분한 메모리를 가지고 있지만, n 번째 cyclotomic 다항식을 생성하는 내장을 사용하지 않습니다. 입력은 임의의 크기 정수이고 출력은 (정확한) 합리적인 계수를 가진 다항식입니다.

여기서 대략적인 아이디어는 다항식을 재귀 적으로 계산하는 것입니다. 위해 n=1또는 n주요 그것은 간단하다. 다른 모든 숫자의 경우이 접근법은 기본적으로 정의 2의 공식을 사용합니다.

에 대한 해결 . 꽤 많은 바이트에 대해 @ H.PWiz에게 감사드립니다!

import Math.Polynomial
import Data.Ratio
import NumberTheory
p=powPoly x
q=poly LE
c n|n<2=q[-1,1%1]|isPrime n=sumPolys$p<$>[0..n-1]|1>0=fst$quotRemPoly(addPoly(p n)$q[-1])$foldl1 multPoly[c d|d<-[1..n-1],n`mod`d<1]

이를 위해 n=105다항식을 얻습니다 (모든 %1분모를 정리했습니다 ).

[1,1,1,0,0,-1,-1,-2,-1,-1,0,0,1,1,1,1,1,1,0,0,-1,0,-1,0,-1,0,-1,0,-1,0,0,1,1,1,1,1,1,0,0,-1,-1,-2,-1,-1,0,0,1,1,1]

의 다항식은 여기n=15015 에서 찾을 수 있습니다 (최대 계수는 23).

온라인으로 사용해보십시오!


+1내장되어 있지 않기 때문에.
DJMcMayhem

@flawr 왜 사용하고 Rationals있습니까? 그들없이 잘 작동하는 것 같습니다
H.PWiz

그렇습니까? 에 문제가있었습니다. quotRemPoly다시 시도하겠습니다!
flawr

아 "문제"는 대신 Double사용하지 않으면 계수를 산출 Ratio Integer하여 매우 (매우) 큰 문제를 일으킬 수 있다는 것입니다 n.
flawr

어 .. 그건 문제가 아닌 것 같아
H.PWiz



2

Mathematica, 81 바이트

Round@CoefficientList[Times@@(x-E^(2Pi*I#/k)&/@Select[Range[k=#],#~GCD~k<2&]),x]&



1

CJam ( 52 51 바이트)

{M{:K,:!W+K,0-{K\%!},{j($,\:Q,-[{(\1$Qf*.-}*;]}/}j}

온라인 데모 . 이것은 익명 블록 (함수)이며 스택에서 정수를 취하고 스택에 계수의 빅 엔디안 배열을 남깁니다.

해부

{                    e# Define a block
  M{                 e#   Memoised recursion with no base cases.
    :K,:!W+          e#     Store argument in K and build (x^K - 1)
    K,0-{K\%!},      e#     Find proper divisors of K
    {                e#     Foreach proper divisor D...
      j              e#       Recursive call to get Dth cyclotomic poly
      ($,\:Q,-       e#       The cleverest bit. We know that it is monic, and the
                     e#       poly division is simpler without that leading 1, so
                     e#       pop it off and use it for a stack-based lookup in
                     e#       calculating the number of terms in the quotient.
                     e#       Ungolfed this was (;:Q1$,\,-
                     e#       Store the headless divisor in Q.
      [              e#       Gather terms into an array...
        {            e#         Repeat the calculated number of times...
          (\         e#           Pop leading term, which goes into the quotient.
          1$Qf*.-    e#           Multiply Q by that term and subtract from tail.
        }*;          e#         Discard the array of Q,( zeroes. 
      ]
    }/
  }j
}

0

자바 스크립트 (ES6), 337 333 284 ... 252 250 245 242 바이트

(v,z=[e=[1,u=0]],g=(x,y)=>y?g(y,x%y):x,h=Math,m=(l,x,p=h.cos(l),q=h.sin(l),i=0)=>x.map(()=>[(i&&(n=x[i-1])[0])-(w=x[i])[0]*p+w[1]*q,(i++&&n[1])-w[1]*p-w[0]*q]))=>{for(;++u<v;z=g(v,u)-1?z:[...m(h.PI*2*u/v,z),e]);return z.map(r=>h.round(r[0]))}

설명 (선택) :

z=[e=[1,u=0]]

z = (1 + 0i) * x ^ 0 초기화

g=(x,y)=>y?g(y,x%y):x

GCD 계산.

h=Math

수학 함수를 꽤 많이 사용해야하기 때문에 여기에서 다른 변수를 사용했습니다.

m=(l,x,p=h.cos(l),q=h.sin(l),i=-1)=>blah blah blah

다항식 곱셈.

for(;++u<v;z=g(v,u)-1?z:[...m(h.PI*2*u/v,z),e]);

사용 된 공식은

여기에 이미지 설명을 입력하십시오

return z.map(r=>h.round(r[0]))

출력을 정수 배열로 다시 압축하십시오.

출력 :

위치 i의 요소가 x ^ i의 계수를 나타내는 정수 배열입니다.

JS의 문제점 중 하나는 JS가 다항식과 복소수 계산을위한 기본 라이브러리를 제공하지 않기 때문에 배열과 같은 방식으로 구현되어야한다는 것입니다.

console.log (phi (105))는

Array(49)
 0:  1    1:  1    2:  1    3: -0    4: -0    5: -1    6: -1 
 7: -2    8: -1    9: -1   10:  0   11: -0   12:  1   13:  1 
14:  1   15:  1   16:  1   17:  1   18:  0   19: -0   20: -1 
21:  0   22: -1   23: -0   24: -1   25:  0   26: -1   27: -0 
28: -1   29:  0   30:  0   31:  1   32:  1   33:  1   34:  1 
35:  1   36:  1   37: -0   38: -0   39: -1   40: -1   41: -2 
42: -1   43: -1   44: -0   45: -0   46:  1   47:  1   48:  1 
length: 49
__proto__: Array(0)

337> 333 (-4) : 정의되지 않은 값을 확인하기위한 코드 변경

333> 284 (-49) : 다항식 곱셈 함수가 단순화 될 수 있으므로 변경되었습니다.

284> 277 (-7) : 일부 중복 코드가 삭제되었습니다.

277> 265 (-12) : 2 요소 배열 대신 2 개의 변수를 사용하여 배열 사용에서 일부 바이트를 삭제

265> 264 (-1) : Array.concat () 대신 Array.push ()를 사용하여 4 바이트를 줄이지 만 for 루프 괄호와 z 변수에 3을 추가했습니다.

264> 263 (-1) : 마지막 개정에서 추가 골프

263> 262 (-1) : for 루프에서 골프를 쳤다

262> 260 (-2) : if 절에서 골프를 쳤다

260> 258 (-2) : 선언을 더 결합

258> 252 (-6) : 배열 참조 재사용으로 골프

252> 250 (-2) : 일부 단항 연산자를 이진 연산자로 바꿉니다.

250> 245 (-5) : Array.map ()의 증분을 카운터의 마지막 참조로 이동하여 바이트를 제거합니다.

245> 242 (-3) : Array.push () 대신에 확산 구문을 사용하십시오

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.