พหุนาม Cyclotomic


17

พื้นหลัง (ข้ามไปที่คำจำกัดความ)

ออยเลอร์พิสูจน์ทฤษฎีบทที่สวยงามเกี่ยวกับจำนวนเชิงซ้อน: e ix = cos (x) + i sin (x)

สิ่งนี้ทำให้ทฤษฎีบทของเดอมอยฟอร์พิสูจน์ได้ง่าย:

(e ix ) n = e i (nx)

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

เราสามารถพล็อตตัวเลขที่ซับซ้อนโดยใช้ระนาบแบบยุคลิดแบบสองมิติโดยมีแกนนอนเป็นตัวแทนของส่วนจริงและแกนตั้งเป็นตัวแทนของส่วนจินตภาพ ด้วยวิธีนี้ (3,4) จะสอดคล้องกับจำนวนเชิงซ้อน 3 + 4i

หากคุณคุ้นเคยกับพิกัดเชิงขั้ว (3,4) จะเป็น (5, arctan (4/3)) ในพิกัดเชิงขั้ว หมายเลขแรก r คือระยะทางของจุดจากจุดกำเนิด ตัวเลขที่สองคือ angle คือมุมที่วัดจากแกน x บวกถึงจุดทวนเข็มนาฬิกา ดังนั้น 3 = r cosθและ 4 = r sinθ ดังนั้นเราจึงสามารถเขียน 3 + 4i เป็น R cosθ + ri sinθ = R (cosθsinθ + i) = ใหม่iθ

ขอให้เราแก้สมการที่ซับซ้อน z n = 1 โดยที่ n เป็นจำนวนเต็มบวก

เราปล่อยให้ Z = ใหม่iθ จากนั้น Z n = R nอีinθ ระยะทางของ z nจากจุดกำเนิดคือrnและมุมคือnθ อย่างไรก็ตามเรารู้ว่าระยะทาง 1 จากจุดกำเนิดคือ 1 และมุมคือ 0 ดังนั้น r n = 1 และnθ = 0 อย่างไรก็ตามหากคุณหมุน2πขึ้นไปคุณจะยังคงอยู่ที่จุดเดียวกันเนื่องจาก2πเป็นเพียงวงกลมเต็ม ดังนั้น r = 1 และnθ = 2kπให้เรา Z = อี2ikπ / n

เราย้ำการค้นพบของเรา: การแก้ปัญหาถึง z n = 1 Z = อี2ikπ / n

พหุนามสามารถแสดงออกในรูปของราก ตัวอย่างเช่นรากของ x 2 -3x + 2 คือ 1 และ 2 ดังนั้น x 2 -3x + 2 = (x-1) (x-2) ในทำนองเดียวกันจากการค้นพบของเราด้านบน:

อย่างไรก็ตามผลิตภัณฑ์นั้นมีรากของเอ็นอื่น ๆ อย่างแน่นอน ตัวอย่างเช่นใช้ n = 8 รากของ z 4 = 1 ก็จะถูกรวมอยู่ในรากของ z 8 = 1 เนื่องจาก z 4 = 1 หมายถึง z 8 = (z 4 ) 2 = 1 2 = 1 ลองใช้ n = 6 เป็นตัวอย่าง ถ้า z 2 = 1 แล้วเราก็จะได้ z 6 = 1 ด้วย เช่นเดียวกันถ้า z 3 = 1 ดังนั้น z 6 = 1

หากเราต้องการแยกรากที่ไม่ซ้ำกับ z n = 1 เราจะต้องมี k และ n เพื่อไม่แชร์ตัวหารร่วมยกเว้น 1 หรืออย่างอื่นถ้าพวกเขาแชร์ตัวหารสามัญ d โดยที่ d> 1 แล้ว z จะเป็น (k / d) -th root ของ z n / d = 1 การใช้เทคนิคด้านบนเพื่อเขียนพหุนามในแง่ของรากเราได้พหุนาม:

โปรดทราบว่าพหุนามนี้ทำโดยลบรากของ z n / d = 1 โดยที่ d เป็นตัวหารของ n เราอ้างว่าพหุนามข้างต้นมีค่าสัมประสิทธิ์จำนวนเต็ม พิจารณา LCM ของพหุนามในรูปแบบของ z n / d -1 โดยที่ d> 1 และ d หาร n รากของ LCM เป็นรากที่เราต้องการลบอย่างแน่นอน เนื่องจากแต่ละองค์ประกอบมีค่าสัมประสิทธิ์จำนวนเต็ม LCM จึงมีค่าสัมประสิทธิ์จำนวนเต็มด้วย เนื่องจาก LCM หาร z n -1 ความฉลาดจึงต้องเป็นพหุนามที่มีสัมประสิทธิ์จำนวนเต็มและความฉลาดทางคือพหุนามข้างต้น

รากของ z n = 1 ทั้งหมดมีรัศมี 1 ดังนั้นพวกมันจึงเกิดเป็นวงกลม พหุนามแสดงถึงจุดของวงกลมที่ไม่ซ้ำกับ n ดังนั้นในแง่หนึ่งชื่อพหุนามสร้างพาร์ติชันของวงกลม ดังนั้นพหุนามข้างบนคือพหุนาม n-th cyclotomic (cyclo- = circle; tom- = to cut)

คำจำกัดความ 1

พหุนาม n-th cyclotomic แสดงว่าเป็นพหุนามที่ไม่ซ้ำกับสัมประสิทธิ์จำนวนเต็มที่แบ่ง x n -1 แต่ไม่ใช่ x k -1 สำหรับ k <n

คำจำกัดความ 2

พหุนาม cyclotomic เป็นชุดของพหุนามหนึ่งชุดสำหรับจำนวนเต็มบวกแต่ละตัวเช่น:

โดยที่ k | n หมายถึง k หาร n

คำจำกัดความ 3

พหุนาม n-th cyclotomic คือพหุนาม 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 - 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

งาน

รับค่าจำนวนเต็มบวกnคืนค่าnพหุนาม -th cyclotomic ตามที่นิยามไว้ข้างต้นในรูปแบบที่เหมาะสม (อนุญาตรายการ ieg ของค่าสัมประสิทธิ์)

กฎระเบียบ

คุณสามารถคืนค่าทศนิยมหรือจำนวนเชิงซ้อนได้ตราบใดที่มันปัดเศษเป็นค่าที่ถูกต้อง

เกณฑ์การให้คะแนน

นี่คือรหัสกอล์ฟคำตอบที่สั้นที่สุดในการชนะไบต์

อ้างอิง


1
อาจเพิ่ม 105 เป็นแบบทดสอบ
Jonathan Allan

@JonathanAllan ฉันไม่ต้องการพิมพ์ 48 คำ
Leaky Nun

1
อนุญาตให้ใช้จุดลอยตัวไม่ถูกต้องหรือไม่
ไมล์

3
@miles ฉันเกลียดการลอยตัวด้วยความหลงใหล> <แต่ฉันจะปกป้องความตายที่คุณมีสิทธิ์ใช้ลอย
Leun Nun

1
เราสามารถส่งออกตัวเลขทศนิยมที่ซับซ้อนได้หรือไม่หากพวกมันให้คำตอบที่ถูกต้องเมื่อปัดเศษเป็นจำนวนเต็ม / เกาส์รัสเซียที่ใกล้ที่สุด?
fireflame241

คำตอบ:


12

Haskell , 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-14เนื่องจากการลอยความไม่แน่นอน วิธีการโดยตรงของการคูณออกเพื่อกู้คืนพหุนามจากรากของมัน

นี่fromIntegerเป็นสัมปทานขนาดใหญ่สำหรับระบบประเภทของ Haskell จะต้องมีวิธีที่ดีกว่า ข้อเสนอแนะยินดีต้อนรับ การจัดการกับรากเหง้าของความเป็นสัญลักษณ์อาจช่วยได้


Haskell , 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]

ลองออนไลน์!

ไม่มีการนำเข้า

ใช้สูตร

คำนวณΦ_n (x) โดยการหาร LHS ด้วยเงื่อนไขอื่น ๆ ใน RHS

ผู้ปฏิบัติ%งานทำการหารพหุนามโดยอาศัยส่วนที่เหลือเป็นศูนย์ ตัวหารจะถือว่าเป็น monic และจะได้รับโดยไม่ต้องนำที่ 1 zipWithและยังมีเลขท้ายอนันต์เพื่อหลีกเลี่ยงการตัดทอนเมื่อทำ


[0,0..]repeat 0เป็นไบต์สั้นกว่า
Laikoni

@flawr แบ่งชื่อพหุนาม ฉันคิดว่ามันเป็นวิธีเดียวกับวิธีแก้ปัญหาของคุณ
xnor

ดูเหมือนสง่างามฉันจะต้องเข้าใกล้พรุ่งนี้ในวันพรุ่งนี้ :)
ข้อผิดพลาด

คำตอบนี้ทำให้ฉันต้องการเรียนรู้ Haskell
Giuseppe

1
@xnor -1 byte
H.PWiz

7

Mathematica, 43 41 ไบต์

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

แน่นอนเราสามารถใช้ในตัว แต่ถ้าเราทำไม่ได้แบ่งนี้x n -1 โดยΦ k ( x ) (คำนวณซ้ำ) สำหรับทุกตัวหารที่เหมาะสมkของn

เราใช้Factorเพื่อรับพหุนามในตอนท้าย ฉันคิดว่าเหตุผลที่งานนี้เป็นx^#-1ปัจจัยที่มีอยู่ในพหุนาม cyclotomic ทั้งหมดของตัวหารของnแล้วเราหารสิ่งที่เราไม่ต้องการ

-2 ไบต์ขอบคุณ Jenny_mathy เขียนใหม่Factorเพื่อใช้กับตัวเศษเท่านั้น


2
มันเยี่ยมมาก! คุณสามารถบันทึกไบต์โดยใช้Factor@
J42161217

@Jenny_mathy การทำเช่นนี้ดูเหมือนจะเป็นการแยกวิเคราะห์Factor[x^#-1]/Times@@...แทน หากเราไม่มีวงเล็บเราก็ต้องการวงเล็บ
Misha Lavrov

1
ตกลง ... แต่ฉันต้องบอกว่าเมื่อฉันทดสอบมันก็ให้ผลลัพธ์ที่ถูกต้อง ...
J42161217

นั่นดูน่าสนใจ. มันหมายความว่าเราสามารถบันทึกไบต์อื่นได้โดยการเขียนมันFactor[x^#-1]/Times@@...และมันก็หมายความว่าฉันไม่มีเงื่อนงำว่ามันทำงานอย่างไร
Misha Lavrov


4

Haskell , 250 236 233 218 216 ไบต์

นี่เป็นเวอร์ชัน verbose (@xnor สามารถทำได้เกือบครึ่งคะแนน ) แต่รับประกันว่าจะทำงานได้nตราบใดที่คุณมีหน่วยความจำเพียงพอ แต่ไม่ได้ใช้ builtin สำหรับสร้างพหุนาม n-th cyclotomic อินพุตเป็นจำนวนเต็มขนาดโดยพลการและเอาต์พุตเป็นพหุนามชนิดที่มีสัมประสิทธิ์ rational (แน่นอน)

แนวคิดคร่าวๆนี่คือแคลคูลัสพหุนามแบบวนซ้ำ สำหรับ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ให้ฉันลองอีกครั้ง!
ข้อบกพร่อง

อา "ปัญหา" คือการที่มันให้Doubleค่าสัมประสิทธิ์ถ้าคุณไม่ได้ใช้Ratio Integerแทนซึ่งอาจทำให้เกิดปัญหาสำหรับขนาดใหญ่มาก (มาก)nที่มีขนาดใหญ่
ข้อบกพร่อง

เอ๊ะ ... ฉันไม่คิดว่าเป็นปัญหา
H.PWiz

3

เยลลี่ 23 ไบต์

R÷
ÆḌÇ€FQœ-@Ç×ı2×ØPÆeÆṛ

ลองออนไลน์!

ส่งออกเป็นรายการของค่าสัมประสิทธิ์

มีจุดลอยตัวและความคลาดเคลื่อนที่ซับซ้อน ท้ายกระดาษทำการปัดเศษเพื่อทำให้เอาต์พุตสวยขึ้น






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

JavaScript (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]))

บีบอัดผลลัพธ์กลับไปที่อาร์เรย์จำนวนเต็ม

ขาออก:

Array (ต้องระบุ) อาร์เรย์ของจำนวนเต็มโดยมีองค์ประกอบที่ตำแหน่ง 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.push () แทน Array.concat () เพื่อลด 4 ไบต์ แต่เพิ่ม 3 สำหรับวงเล็บปีกกา for-loop และตัวแปร z

264> 263 (-1): เล่นกอล์ฟเพิ่มเติมในการแก้ไขครั้งล่าสุด

263> 262 (-1): เล่นกอล์ฟบน for loop

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.