Problem Summary

For each relevant pair \((p,q)\), the task is to evaluate the oriented area of a regular star polygon with \(p\)-fold symmetry and step parameter \(q\), then add those area values over a Fibonacci-driven family of pairs. The C++, Python, and Java implementations do not build the polygon vertex by vertex and they do not solve line intersections explicitly. Instead, they use a trigonometric formula for one repeated sector contribution and then scale it by symmetry.

With Fibonacci numbers \(F_1=F_2=1\), the implementations ultimately sum the area quantity for the pairs \((F_m,F_{m-2})\) with \(m=4,5,\dots,35\). The mathematical problem is therefore to turn each star polygon area into a stable one-dimensional sum and then accumulate those sums accurately.

Mathematical Approach

Let \(\mathcal{A}(p,q)\) denote the oriented area quantity used by the implementations. The core idea is that regular symmetry reduces the geometry to a single angular increment, and that increment can be handled with tangent identities instead of coordinate-heavy geometry.

Step 1: Use the Fundamental Angle

For a \(p\)-fold regular figure, the natural angular unit is

$$\delta=\frac{\pi}{p}.$$

The implementations work with the sequence of angles

$$\theta_k=k\delta \qquad (k\ge 1).$$

Rather than describing the star polygon through Cartesian coordinates, the area computation is expressed directly in terms of \(\sin(\theta_k)\), \(\cos(\theta_k)\), and \(\tan(\theta_k)\). This is enough because every contribution depends only on consecutive angles \((k-1)\delta\) and \(k\delta\).

Step 2: Convert Each Local Contribution into a Tangent Difference

The local building block appearing in the implementations is

$$\frac{\sin\delta}{\cos((k-1)\delta)\cos(k\delta)}.$$

Now apply the standard identity

$$\tan u-\tan v=\frac{\sin(u-v)}{\cos u\cos v}.$$

With \(u=k\delta\) and \(v=(k-1)\delta\), we get \(u-v=\delta\), so

$$\frac{\sin\delta}{\cos((k-1)\delta)\cos(k\delta)}=\tan(k\delta)-\tan((k-1)\delta).$$

This matters because the geometry becomes a sum of simple first differences of tangent values. No explicit polygon clipping or line-intersection algebra is required.

Step 3: Assemble the Signed Sector Sum

The implementations form the alternating sum

$$T(p,q)=\sum_{k=2}^{q}(-1)^k\frac{\sin\delta}{\cos((k-1)\delta)\cos(k\delta)}.$$

Using the identity above, this is equivalently

$$T(p,q)=\sum_{k=2}^{q}(-1)^k\left(\tan(k\delta)-\tan((k-1)\delta)\right).$$

The final area quantity is then

$$\mathcal{A}(p,q)=p(-1)^q\left(T(p,q)-\tan\delta\right).$$

The factor \(p\) reflects the \(p\)-fold rotational symmetry: once one representative angular contribution is known, the whole figure is obtained by repeating it \(p\) times. The alternating sign inside the sum and the outer factor \((-1)^q\) encode the orientation pattern used by the formula.

Step 4: Advance the Angles Recursively

Computing \(\sin(k\delta)\) and \(\cos(k\delta)\) from scratch for every \(k\) would be unnecessary. The implementations instead use the addition formulas

$$\sin((k+1)\delta)=\sin(k\delta)\cos\delta+\cos(k\delta)\sin\delta,$$

$$\cos((k+1)\delta)=\cos(k\delta)\cos\delta-\sin(k\delta)\sin\delta.$$

So after one initial evaluation of \(\sin\delta\) and \(\cos\delta\), the next angle is generated by recurrence. This keeps the inner loop lightweight and matches exactly what the code does.

Step 5: Sum over Fibonacci-Indexed Pairs

The generated Fibonacci list begins

$$1,1,2,3,5,8,\dots$$

and the implementations take pairs separated by two positions. Rewritten in standard Fibonacci notation, the total is

$$\sum_{m=4}^{35}\mathcal{A}(F_m,F_{m-2}).$$

This indexing is important: it is more precise than saying merely that the inputs are “Fibonacci-based”. Each area evaluation is tied to one specific pair \((F_m,F_{m-2})\).

Worked Example: \(\mathcal{A}(8,3)\)

For \(p=8\) and \(q=3\),

$$\delta=\frac{\pi}{8},\qquad \tan\delta=\sqrt{2}-1,\qquad \tan(2\delta)=1,\qquad \tan(3\delta)=\sqrt{2}+1.$$

The alternating inner sum has two terms:

$$\begin{aligned} T(8,3) &=\left(\tan\frac{\pi}{4}-\tan\frac{\pi}{8}\right)-\left(\tan\frac{3\pi}{8}-\tan\frac{\pi}{4}\right)\\ &=\left(1-(\sqrt{2}-1)\right)-\left((\sqrt{2}+1)-1\right)\\ &=2-2\sqrt{2}. \end{aligned}$$

Subtract the extra base term:

$$T(8,3)-\tan\delta=(2-2\sqrt{2})-(\sqrt{2}-1)=3-3\sqrt{2}.$$

Because \(q=3\) is odd, \((-1)^q=-1\). Therefore

$$\mathcal{A}(8,3)=8(-1)(3-3\sqrt{2})=24(\sqrt{2}-1)\approx 9.9411254970.$$

This is exactly the small numerical checkpoint reproduced by the implementations.

How the Code Works

The C++, Python, and Java implementations all follow the same structure. First they generate the needed Fibonacci values. For each pair \((p,q)\), they compute \(\delta\), \(\sin\delta\), \(\cos\delta\), and \(\tan\delta\). Then an inner loop runs from \(k=2\) to \(q\), advances \(\sin(k\delta)\) and \(\cos(k\delta)\) with the recurrence above, forms the quotient \(\sin\delta/(\cos((k-1)\delta)\cos(k\delta))\), applies the alternating sign, and adds the result to a compensated running total.

After the inner loop ends, the implementation subtracts \(\tan\delta\), multiplies by \(p(-1)^q\), and obtains one area value. The outer Fibonacci sum is also accumulated with compensated summation, because many contributions have opposite signs and similar magnitudes. Finally the result is formatted to 10 decimal places.

Complexity Analysis

One evaluation of \(\mathcal{A}(p,q)\) uses \(O(q)\) arithmetic steps and \(O(1)\) extra memory. Over the full problem range, the total cost is

$$O\left(\sum_{m=4}^{35}F_{m-2}\right)=O(F_{35}),$$

which is a fixed and very manageable amount of work. In exact terms, the inner loop executes

$$\sum_{j=2}^{33}F_j=F_{35}-2=9{,}227{,}463$$

iterations in total. Memory usage remains \(O(1)\) apart from the short Fibonacci table.

Footnotes and References

  1. Problem page: https://projecteuler.net/problem=841
  2. Regular star polygons: Wikipedia - Star polygon
  3. Tangent identities: Wikipedia - List of trigonometric identities
  4. Fibonacci numbers: Wikipedia - Fibonacci number
  5. Kahan summation algorithm: Wikipedia - Kahan summation algorithm

Problemzusammenfassung

Für jedes relevante Paar \((p,q)\) soll die orientierte Fläche eines regulären Sternpolygons mit \(p\)-facher Symmetrie und Schrittparameter \(q\) berechnet werden. Anschließend werden diese Flächenwerte über eine Fibonacci-gesteuerte Familie von Paaren aufsummiert. Die C++, Python- und Java-Implementierungen konstruieren weder alle Eckpunkte noch berechnen sie explizit Schnittpunkte von Geraden. Stattdessen benutzen sie eine trigonometrische Formel für einen wiederkehrenden Sektorbeitrag und skalieren diesen per Symmetrie.

Mit den Fibonacci-Zahlen \(F_1=F_2=1\) wird schließlich über die Paare \((F_m,F_{m-2})\) für \(m=4,5,\dots,35\) summiert. Das eigentliche Problem ist also eine numerisch stabile Auswertung vieler Sternpolygon-Flächen und keine rohe geometrische Simulation.

Mathematischer Ansatz

Sei \(\mathcal{A}(p,q)\) die orientierte Flächengröße, die von den Implementierungen berechnet wird. Der Kern der Methode besteht darin, die reguläre Geometrie auf einen elementaren Winkel zurückzuführen und die resultierenden Terme mit Tangens-Identitäten auszuwerten.

Schritt 1: Der fundamentale Winkel

Für eine reguläre Figur mit \(p\)-facher Symmetrie ist die natürliche Winkeleinheit

$$\delta=\frac{\pi}{p}.$$

Gearbeitet wird mit der Folge

$$\theta_k=k\delta \qquad (k\ge 1).$$

Statt kartesische Koordinaten aller Punkte zu verfolgen, drückt die Lösung die Flächenbeiträge direkt über \(\sin(\theta_k)\), \(\cos(\theta_k)\) und \(\tan(\theta_k)\) aus. Entscheidend sind dabei nur aufeinanderfolgende Winkel \((k-1)\delta\) und \(k\delta\).

Schritt 2: Lokalen Beitrag in eine Tangensdifferenz umformen

Der zentrale Baustein lautet

$$\frac{\sin\delta}{\cos((k-1)\delta)\cos(k\delta)}.$$

Nun verwendet man die Identität

$$\tan u-\tan v=\frac{\sin(u-v)}{\cos u\cos v}.$$

Mit \(u=k\delta\) und \(v=(k-1)\delta\) folgt \(u-v=\delta\), also

$$\frac{\sin\delta}{\cos((k-1)\delta)\cos(k\delta)}=\tan(k\delta)-\tan((k-1)\delta).$$

Damit wird die Geometrie zu einer Summe einfacher erster Differenzen von Tangenswerten. Weder Polygon-Clipping noch explizite Schnittpunktformeln sind nötig.

Schritt 3: Die alternierende Sektorsumme

Die Implementierungen bilden

$$T(p,q)=\sum_{k=2}^{q}(-1)^k\frac{\sin\delta}{\cos((k-1)\delta)\cos(k\delta)}.$$

Mit der vorherigen Umformung ist das äquivalent zu

$$T(p,q)=\sum_{k=2}^{q}(-1)^k\left(\tan(k\delta)-\tan((k-1)\delta)\right).$$

Die endgültige Flächenformel ist

$$\mathcal{A}(p,q)=p(-1)^q\left(T(p,q)-\tan\delta\right).$$

Der Faktor \(p\) spiegelt die \(p\)-fache Rotationssymmetrie wider: Kennt man einen repräsentativen Winkelbeitrag, erhält man die Gesamtfigur durch \(p\)-fache Wiederholung. Die Vorzeichen kodieren die in der Formel benutzte Orientierung.

Schritt 4: Winkel rekursiv fortschreiben

\(\sin(k\delta)\) und \(\cos(k\delta)\) werden nicht in jedem Schleifendurchlauf neu mit trigonometrischen Funktionen berechnet. Stattdessen nutzen die Implementierungen die Additionsformeln

$$\sin((k+1)\delta)=\sin(k\delta)\cos\delta+\cos(k\delta)\sin\delta,$$

$$\cos((k+1)\delta)=\cos(k\delta)\cos\delta-\sin(k\delta)\sin\delta.$$

Nach einer initialen Auswertung von \(\sin\delta\) und \(\cos\delta\) wird jeder weitere Winkel rekursiv erzeugt. Genau so arbeitet auch der Code in der inneren Schleife.

Schritt 5: Äußere Summe über Fibonacci-Paare

Die erzeugte Fibonacci-Folge beginnt mit

$$1,1,2,3,5,8,\dots$$

und die Implementierungen wählen jeweils zwei Einträge mit Abstand \(2\). In Standardnotation ergibt sich die Gesamtsumme als

$$\sum_{m=4}^{35}\mathcal{A}(F_m,F_{m-2}).$$

Diese Indexierung ist ein wichtiger Detailpunkt: Die Rechnung läuft nicht über beliebige Fibonacci-Paare, sondern genau über diese feste Folge von Eingaben.

Durchgerechnetes Beispiel: \(\mathcal{A}(8,3)\)

Für \(p=8\) und \(q=3\) gilt

$$\delta=\frac{\pi}{8},\qquad \tan\delta=\sqrt{2}-1,\qquad \tan(2\delta)=1,\qquad \tan(3\delta)=\sqrt{2}+1.$$

Die alternierende Innensumme hat zwei Terme:

$$\begin{aligned} T(8,3) &=\left(\tan\frac{\pi}{4}-\tan\frac{\pi}{8}\right)-\left(\tan\frac{3\pi}{8}-\tan\frac{\pi}{4}\right)\\ &=\left(1-(\sqrt{2}-1)\right)-\left((\sqrt{2}+1)-1\right)\\ &=2-2\sqrt{2}. \end{aligned}$$

Danach wird der Basisterm abgezogen:

$$T(8,3)-\tan\delta=(2-2\sqrt{2})-(\sqrt{2}-1)=3-3\sqrt{2}.$$

Da \(q=3\) ungerade ist, gilt \((-1)^q=-1\). Also

$$\mathcal{A}(8,3)=8(-1)(3-3\sqrt{2})=24(\sqrt{2}-1)\approx 9.9411254970.$$

Genau dieser Wert erscheint als kleiner numerischer Kontrollpunkt der Implementierungen.

Wie der Code arbeitet

Die C++, Python- und Java-Implementierungen folgen demselben Ablauf. Zuerst werden die benötigten Fibonacci-Zahlen erzeugt. Für jedes Paar \((p,q)\) berechnen sie \(\delta\), \(\sin\delta\), \(\cos\delta\) und \(\tan\delta\). Dann läuft eine innere Schleife von \(k=2\) bis \(q\), die \(\sin(k\delta)\) und \(\cos(k\delta)\) per Rekursion fortschreibt, den Quotienten \(\sin\delta/(\cos((k-1)\delta)\cos(k\delta))\) bildet, das passende Vorzeichen anlegt und alles in eine kompensierte laufende Summe einträgt.

Nach Ende der inneren Schleife zieht die Implementierung \(\tan\delta\) ab, multipliziert mit \(p(-1)^q\) und erhält so einen Flächenwert. Die äußere Fibonacci-Summe wird ebenfalls mit kompensierter Summation aufgebaut, weil viele Beiträge unterschiedliche Vorzeichen und ähnliche Größenordnungen haben. Abschließend wird das Resultat mit 10 Nachkommastellen ausgegeben.

Komplexitätsanalyse

Eine Auswertung von \(\mathcal{A}(p,q)\) benötigt \(O(q)\) Rechenschritte und \(O(1)\) zusätzlichen Speicher. Über den gesamten Aufgabenbereich ergibt sich

$$O\left(\sum_{m=4}^{35}F_{m-2}\right)=O(F_{35}),$$

also ein fester und gut beherrschbarer Aufwand. Exakt ausgeführt wird die innere Schleife insgesamt

$$\sum_{j=2}^{33}F_j=F_{35}-2=9{,}227{,}463$$

Mal. Der Speicherbedarf bleibt abgesehen von der kurzen Fibonacci-Tabelle bei \(O(1)\).

Fußnoten und Quellen

  1. Problemseite: https://projecteuler.net/problem=841
  2. Reguläre Sternpolygone: Wikipedia - Sternpolygon
  3. Trigonometrische Identitäten: Wikipedia - Formelsammlung Trigonometrie
  4. Fibonacci-Zahlen: Wikipedia - Fibonacci-Folge
  5. Kahan-Summation: Wikipedia - Kahan summation algorithm

Problem Özeti

Her ilgili \((p,q)\) çifti için amaç, \(p\)-kat dönel simetriye ve \(q\) adım parametresine sahip düzenli yıldız çokgenin yönlü alanını hesaplamak ve sonra bu alanları Fibonacci tabanlı bir çift ailesi üzerinde toplamaktır. C++, Python ve Java uygulamaları çokgeni köşe köşe inşa etmez ve doğru kesişimlerini doğrudan çözmez. Bunun yerine tekrarlanan tek bir açısal katkı için trigonometrik bir formül kullanır ve simetriyle tüm alana ulaşır.

\(F_1=F_2=1\) olacak şekilde Fibonacci sayıları alınırsa, uygulamalar son toplamı \((F_m,F_{m-2})\) çiftleri için \(m=4,5,\dots,35\) aralığında hesaplar. Dolayısıyla asıl mesele kaba kuvvetle geometri çizmek değil, her yıldız çokgen alanını kararlı bir tek boyutlu toplamla ifade etmektir.

Matematiksel Yaklaşım

\(\mathcal{A}(p,q)\) ile uygulamaların hesapladığı yönlü alan büyüklüğünü gösterelim. Yöntemin özü, düzenli yapıyı tek bir temel açıya indirgemek ve ortaya çıkan terimleri tanjant özdeşlikleriyle sadeleştirmektir.

Adım 1: Temel açıyı kur

\(p\)-kat simetri için doğal açısal birim

$$\delta=\frac{\pi}{p}.$$

Uygulamalar şu açı dizisi üzerinde çalışır:

$$\theta_k=k\delta \qquad (k\ge 1).$$

Tüm noktaları Kartezyen düzlemde izlemek yerine, alan hesabı doğrudan \(\sin(\theta_k)\), \(\cos(\theta_k)\) ve \(\tan(\theta_k)\) üzerinden yürütülür. Çünkü her yerel katkı yalnızca ardışık iki açıya, yani \((k-1)\delta\) ile \(k\delta\)'ya bağlıdır.

Adım 2: Yerel katkıyı tanjant farkına çevir

Uygulamalarda tekrar tekrar görünen temel ifade

$$\frac{\sin\delta}{\cos((k-1)\delta)\cos(k\delta)}$$

şeklindedir. Şimdi standart özdeşliği kullanalım:

$$\tan u-\tan v=\frac{\sin(u-v)}{\cos u\cos v}.$$

\(u=k\delta\) ve \(v=(k-1)\delta\) seçilirse \(u-v=\delta\) olur ve

$$\frac{\sin\delta}{\cos((k-1)\delta)\cos(k\delta)}=\tan(k\delta)-\tan((k-1)\delta)$$

elde edilir. Böylece geometri, tanjantların basit birinci farklarının toplamına dönüşür; açık kesişim denklemlerine ihtiyaç kalmaz.

Adım 3: İşaretli sektör toplamını kur

Uygulamalar şu alternatif işaretli toplamı hesaplar:

$$T(p,q)=\sum_{k=2}^{q}(-1)^k\frac{\sin\delta}{\cos((k-1)\delta)\cos(k\delta)}.$$

Bir önceki özdeşlikle bu toplam eşdeğer olarak

$$T(p,q)=\sum_{k=2}^{q}(-1)^k\left(\tan(k\delta)-\tan((k-1)\delta)\right)$$

şeklinde yazılır. Son alan formülü ise

$$\mathcal{A}(p,q)=p(-1)^q\left(T(p,q)-\tan\delta\right).$$

Buradaki \(p\) katsayısı \(p\)-kat dönel simetriyi yansıtır: temsilî tek bir açısal katkı bulunduğunda tüm şekil \(p\) kopya ile tamamlanır. İç toplamın işaretleri ve dıştaki \((-1)^q\) faktörü, formülün kullandığı yön bilgisini taşır.

Adım 4: Açıları özyinelemeli ilerlet

Her döngü adımında \(\sin(k\delta)\) ve \(\cos(k\delta)\) değerlerini baştan hesaplamak gereksiz olurdu. Bunun yerine uygulamalar toplama formüllerini kullanır:

$$\sin((k+1)\delta)=\sin(k\delta)\cos\delta+\cos(k\delta)\sin\delta,$$

$$\cos((k+1)\delta)=\cos(k\delta)\cos\delta-\sin(k\delta)\sin\delta.$$

Böylece \(\sin\delta\) ve \(\cos\delta\) bir kez hesaplandıktan sonra sonraki açılar yinelemeli olarak üretilir. Kodun iç döngüsünde yapılan işlem tam olarak budur.

Adım 5: Fibonacci çiftleri üzerinde dış toplam

Üretilen Fibonacci dizisi

$$1,1,2,3,5,8,\dots$$

diye başlar ve uygulamalar iki indeks aralıklı çiftleri seçer. Standart Fibonacci gösterimiyle toplam

$$\sum_{m=4}^{35}\mathcal{A}(F_m,F_{m-2})$$

olur. Bu ayrıntı önemlidir; hesap herhangi bir Fibonacci çifti üzerinde değil, tam olarak bu sabit giriş dizisi üzerinde yapılır.

Çalışılmış Örnek: \(\mathcal{A}(8,3)\)

\(p=8\) ve \(q=3\) için

$$\delta=\frac{\pi}{8},\qquad \tan\delta=\sqrt{2}-1,\qquad \tan(2\delta)=1,\qquad \tan(3\delta)=\sqrt{2}+1.$$

İç toplamda iki terim vardır:

$$\begin{aligned} T(8,3) &=\left(\tan\frac{\pi}{4}-\tan\frac{\pi}{8}\right)-\left(\tan\frac{3\pi}{8}-\tan\frac{\pi}{4}\right)\\ &=\left(1-(\sqrt{2}-1)\right)-\left((\sqrt{2}+1)-1\right)\\ &=2-2\sqrt{2}. \end{aligned}$$

Ek temel terimi çıkarınca

$$T(8,3)-\tan\delta=(2-2\sqrt{2})-(\sqrt{2}-1)=3-3\sqrt{2}$$

elde edilir. \(q=3\) tek olduğu için \((-1)^q=-1\) olur. Dolayısıyla

$$\mathcal{A}(8,3)=8(-1)(3-3\sqrt{2})=24(\sqrt{2}-1)\approx 9.9411254970.$$

Bu, uygulamaların yeniden ürettiği küçük sayısal kontrol değeridir.

Kod Nasıl Çalışır

C++, Python ve Java uygulamalarının akışı aynıdır. Önce gerekli Fibonacci değerleri üretilir. Her \((p,q)\) çifti için \(\delta\), \(\sin\delta\), \(\cos\delta\) ve \(\tan\delta\) hesaplanır. Sonra \(k=2\)'den \(q\)'ya kadar giden iç döngü, yukarıdaki özyineleme ile \(\sin(k\delta)\) ve \(\cos(k\delta)\) değerlerini ilerletir, \(\sin\delta/(\cos((k-1)\delta)\cos(k\delta))\) oranını kurar, doğru işareti uygular ve sonucu telafili bir koşan toplamda biriktirir.

İç döngü bittiğinde uygulama \(\tan\delta\)'yı çıkarır, \(p(-1)^q\) ile çarpar ve tek bir alan değeri elde eder. Dış Fibonacci toplamı da telafili toplama ile yürütülür; çünkü birçok katkı zıt işaretli ve birbirine yakın büyüklüktedir. Sonuç en sonda 10 ondalık basamakla yazdırılır.

Karmaşıklık Analizi

Bir \(\mathcal{A}(p,q)\) hesabı \(O(q)\) aritmetik adım ve \(O(1)\) ek bellek kullanır. Tüm problem aralığında toplam maliyet

$$O\left(\sum_{m=4}^{35}F_{m-2}\right)=O(F_{35})$$

şeklindedir ve sabit bir iş yüküdür. Tam sayarsak iç döngü toplam

$$\sum_{j=2}^{33}F_j=F_{35}-2=9{,}227{,}463$$

kez çalışır. Kısa Fibonacci tablosu dışında bellek kullanımı \(O(1)\) olarak kalır.

Dipnotlar ve Kaynaklar

  1. Problem sayfası: https://projecteuler.net/problem=841
  2. Yıldız çokgenler: Wikipedia - Yıldız çokgen
  3. Trigonometrik özdeşlikler: Wikipedia - List of trigonometric identities
  4. Fibonacci sayıları: Wikipedia - Fibonacci sayıları
  5. Kahan toplama algoritması: Wikipedia - Kahan summation algorithm

Resumen del Problema

Para cada par relevante \((p,q)\), hay que evaluar el área orientada de un polígono estrellado regular con simetría de orden \(p\) y parámetro de salto \(q\), y después sumar esos valores sobre una familia de pares definida por Fibonacci. Las implementaciones en C++, Python y Java no construyen el polígono vértice por vértice ni calculan intersecciones de rectas de forma explícita. En lugar de eso, usan una fórmula trigonométrica para una contribución sectorial repetida y luego la amplían mediante simetría.

Si \(F_1=F_2=1\), el total que se calcula es la suma sobre los pares \((F_m,F_{m-2})\) con \(m=4,5,\dots,35\). Por tanto, el reto real es convertir cada área en una suma unidimensional numéricamente estable y no hacer una simulación geométrica directa.

Enfoque Matemático

Denotemos por \(\mathcal{A}(p,q)\) la cantidad de área orientada que usan las implementaciones. La idea central es reducir la geometría regular a un único incremento angular y transformar los términos resultantes con identidades de tangente.

Paso 1: Fijar el ángulo fundamental

Para una figura regular con simetría de orden \(p\), la unidad angular natural es

$$\delta=\frac{\pi}{p}.$$

Las implementaciones trabajan con la sucesión

$$\theta_k=k\delta \qquad (k\ge 1).$$

En vez de seguir todas las coordenadas cartesianas del dibujo, la fórmula expresa los aportes de área directamente con \(\sin(\theta_k)\), \(\cos(\theta_k)\) y \(\tan(\theta_k)\). Esto basta porque cada contribución local depende solo de los ángulos consecutivos \((k-1)\delta\) y \(k\delta\).

Paso 2: Reescribir cada aporte local como diferencia de tangentes

El bloque básico que aparece en las implementaciones es

$$\frac{\sin\delta}{\cos((k-1)\delta)\cos(k\delta)}.$$

Ahora usamos la identidad estándar

$$\tan u-\tan v=\frac{\sin(u-v)}{\cos u\cos v}.$$

Tomando \(u=k\delta\) y \(v=(k-1)\delta\), se tiene \(u-v=\delta\), y por tanto

$$\frac{\sin\delta}{\cos((k-1)\delta)\cos(k\delta)}=\tan(k\delta)-\tan((k-1)\delta).$$

Así, la geometría se convierte en una suma de primeras diferencias de tangentes. No hace falta resolver intersecciones ni reconstruir la figura completa.

Paso 3: Formar la suma sectorial con signo

Las implementaciones calculan la suma alternante

$$T(p,q)=\sum_{k=2}^{q}(-1)^k\frac{\sin\delta}{\cos((k-1)\delta)\cos(k\delta)}.$$

Usando la identidad anterior, esto equivale a

$$T(p,q)=\sum_{k=2}^{q}(-1)^k\left(\tan(k\delta)-\tan((k-1)\delta)\right).$$

La fórmula final del área es

$$\mathcal{A}(p,q)=p(-1)^q\left(T(p,q)-\tan\delta\right).$$

El factor \(p\) refleja la simetría rotacional: una vez conocido un sector representativo, el total se obtiene repitiéndolo \(p\) veces. Los signos alternantes y el factor exterior \((-1)^q\) codifican la orientación empleada en la expresión.

Paso 4: Avanzar los ángulos con una recurrencia

Sería innecesario recalcular \(\sin(k\delta)\) y \(\cos(k\delta)\) desde cero para cada \(k\). Por eso las implementaciones usan

$$\sin((k+1)\delta)=\sin(k\delta)\cos\delta+\cos(k\delta)\sin\delta,$$

$$\cos((k+1)\delta)=\cos(k\delta)\cos\delta-\sin(k\delta)\sin\delta.$$

Después de una única evaluación inicial de \(\sin\delta\) y \(\cos\delta\), todos los ángulos siguientes se generan recursivamente. Eso coincide exactamente con la lógica del bucle interno.

Paso 5: Sumar sobre los pares de Fibonacci

La sucesión de Fibonacci utilizada empieza como

$$1,1,2,3,5,8,\dots$$

y las implementaciones toman parejas separadas por dos posiciones. En notación estándar, el total calculado es

$$\sum_{m=4}^{35}\mathcal{A}(F_m,F_{m-2}).$$

Esta reindexación importa: no se trata de “algún” conjunto de pares de Fibonacci, sino exactamente de esa lista finita de entradas.

Ejemplo Desarrollado: \(\mathcal{A}(8,3)\)

Para \(p=8\) y \(q=3\),

$$\delta=\frac{\pi}{8},\qquad \tan\delta=\sqrt{2}-1,\qquad \tan(2\delta)=1,\qquad \tan(3\delta)=\sqrt{2}+1.$$

La suma interior alternante tiene dos términos:

$$\begin{aligned} T(8,3) &=\left(\tan\frac{\pi}{4}-\tan\frac{\pi}{8}\right)-\left(\tan\frac{3\pi}{8}-\tan\frac{\pi}{4}\right)\\ &=\left(1-(\sqrt{2}-1)\right)-\left((\sqrt{2}+1)-1\right)\\ &=2-2\sqrt{2}. \end{aligned}$$

Después se resta el término base:

$$T(8,3)-\tan\delta=(2-2\sqrt{2})-(\sqrt{2}-1)=3-3\sqrt{2}.$$

Como \(q=3\) es impar, \((-1)^q=-1\). Por tanto,

$$\mathcal{A}(8,3)=8(-1)(3-3\sqrt{2})=24(\sqrt{2}-1)\approx 9.9411254970.$$

Ese es exactamente el valor numérico pequeño que reproducen las implementaciones.

Cómo Funciona el Código

Las implementaciones en C++, Python y Java siguen la misma estructura. Primero generan los valores de Fibonacci necesarios. Para cada par \((p,q)\), calculan \(\delta\), \(\sin\delta\), \(\cos\delta\) y \(\tan\delta\). Luego un bucle interno recorre \(k=2,3,\dots,q\), actualiza \(\sin(k\delta)\) y \(\cos(k\delta)\) mediante la recurrencia anterior, forma el cociente \(\sin\delta/(\cos((k-1)\delta)\cos(k\delta))\), aplica el signo alternante y lo añade a una suma compensada.

Cuando termina el bucle interior, la implementación resta \(\tan\delta\), multiplica por \(p(-1)^q\) y obtiene un área. La suma exterior sobre los pares de Fibonacci también se hace con compensación, porque muchas contribuciones tienen signos opuestos y magnitudes cercanas. Al final, el resultado se formatea con 10 cifras decimales.

Análisis de Complejidad

Una evaluación de \(\mathcal{A}(p,q)\) cuesta \(O(q)\) operaciones aritméticas y \(O(1)\) memoria adicional. Sobre todo el rango del problema, el coste total es

$$O\left(\sum_{m=4}^{35}F_{m-2}\right)=O(F_{35}),$$

que sigue siendo una cantidad fija y perfectamente manejable. En términos exactos, el bucle interno se ejecuta

$$\sum_{j=2}^{33}F_j=F_{35}-2=9{,}227{,}463$$

veces en total. El uso de memoria permanece en \(O(1)\) aparte de la breve tabla de Fibonacci.

Notas y Referencias

  1. Página del problema: https://projecteuler.net/problem=841
  2. Polígonos estrellados regulares: Wikipedia - Polígono estrellado
  3. Identidades trigonométricas: Wikipedia - Identidad trigonométrica
  4. Números de Fibonacci: Wikipedia - Sucesión de Fibonacci
  5. Algoritmo de suma de Kahan: Wikipedia - Kahan summation algorithm

问题概述

对每一个相关的 \((p,q)\) 对,本题都要计算一个具有 \(p\) 重旋转对称性、步长参数为 \(q\) 的规则星形多边形的有向面积,然后把这些面积沿着一组由 Fibonacci 数给出的参数对累加起来。C++、Python 和 Java 的实现都没有逐点构造整个图形,也没有显式求出所有线段交点;它们采用的是一个单扇区三角公式,再利用对称性放大到整张图。

若记 \(F_1=F_2=1\),那么实现实际求和的对象是 \((F_m,F_{m-2})\),其中 \(m=4,5,\dots,35\)。因此,这道题的核心不是“画图再求面积”,而是把每个星形多边形的面积化成一个稳定的单变量求和公式。

数学方法

记 \(\mathcal{A}(p,q)\) 为实现所计算的有向面积量。整个方法的关键在于:规则结构只需要一个基础角度 \(\delta\),而每个局部项都能借助正切恒等式改写成容易累加的形式。

步骤 1:建立基本角度

对于一个具有 \(p\) 重对称性的规则图形,最自然的角度单位是

$$\delta=\frac{\pi}{p}.$$

实现里真正跟踪的是角序列

$$\theta_k=k\delta \qquad (k\ge 1).$$

也就是说,程序不需要把所有顶点坐标都写出来,只需维护 \(\sin(\theta_k)\)、\(\cos(\theta_k)\) 和 \(\tan(\theta_k)\) 即可,因为每一个局部面积贡献只依赖相邻的两个角 \((k-1)\delta\) 与 \(k\delta\)。

步骤 2:把局部项改写成正切差

实现中反复出现的基本表达式是

$$\frac{\sin\delta}{\cos((k-1)\delta)\cos(k\delta)}.$$

利用标准恒等式

$$\tan u-\tan v=\frac{\sin(u-v)}{\cos u\cos v}$$

并取 \(u=k\delta\)、\(v=(k-1)\delta\),就有 \(u-v=\delta\),因此

$$\frac{\sin\delta}{\cos((k-1)\delta)\cos(k\delta)}=\tan(k\delta)-\tan((k-1)\delta).$$

这一步非常重要,因为它把几何问题转成了正切值的一阶差分求和。这样就不必显式做复杂的交点几何。

步骤 3:构造带交替符号的扇区和

实现先计算下面这个交替求和:

$$T(p,q)=\sum_{k=2}^{q}(-1)^k\frac{\sin\delta}{\cos((k-1)\delta)\cos(k\delta)}.$$

借助上一步,可写成等价形式

$$T(p,q)=\sum_{k=2}^{q}(-1)^k\left(\tan(k\delta)-\tan((k-1)\delta)\right).$$

最终面积公式是

$$\mathcal{A}(p,q)=p(-1)^q\left(T(p,q)-\tan\delta\right).$$

这里的 \(p\) 直接反映 \(p\) 重旋转对称性:只要算出一个代表性扇区的贡献,整个图形就相当于把它复制 \(p\) 次。内部交替符号和外部的 \((-1)^q\) 共同编码了所使用的方向约定。

步骤 4:用递推推进角度

如果每个 \(k\) 都重新调用三角函数去算 \(\sin(k\delta)\) 和 \(\cos(k\delta)\),会做很多重复工作。实现采用的是加法公式递推:

$$\sin((k+1)\delta)=\sin(k\delta)\cos\delta+\cos(k\delta)\sin\delta,$$

$$\cos((k+1)\delta)=\cos(k\delta)\cos\delta-\sin(k\delta)\sin\delta.$$

因此,只要先算一次 \(\sin\delta\) 和 \(\cos\delta\),后面的角就能逐步推出。这与代码中的内层循环完全一致,也减少了重复的三角函数调用。

步骤 5:在 Fibonacci 参数对上做外层求和

实现生成的 Fibonacci 序列起始为

$$1,1,2,3,5,8,\dots$$

并且总是取相隔两个位置的一对值。改写成标准记号后,总和就是

$$\sum_{m=4}^{35}\mathcal{A}(F_m,F_{m-2}).$$

这一步值得明确写出,因为它说明了外层并不是随意枚举若干 Fibonacci 对,而是精确地按这条固定索引规则求和。

算例:\(\mathcal{A}(8,3)\)

取 \(p=8\)、\(q=3\),则

$$\delta=\frac{\pi}{8},\qquad \tan\delta=\sqrt{2}-1,\qquad \tan(2\delta)=1,\qquad \tan(3\delta)=\sqrt{2}+1.$$

此时内层交替和只有两项:

$$\begin{aligned} T(8,3) &=\left(\tan\frac{\pi}{4}-\tan\frac{\pi}{8}\right)-\left(\tan\frac{3\pi}{8}-\tan\frac{\pi}{4}\right)\\ &=\left(1-(\sqrt{2}-1)\right)-\left((\sqrt{2}+1)-1\right)\\ &=2-2\sqrt{2}. \end{aligned}$$

再减去额外的基准项:

$$T(8,3)-\tan\delta=(2-2\sqrt{2})-(\sqrt{2}-1)=3-3\sqrt{2}.$$

因为 \(q=3\) 为奇数,所以 \((-1)^q=-1\)。于是

$$\mathcal{A}(8,3)=8(-1)(3-3\sqrt{2})=24(\sqrt{2}-1)\approx 9.9411254970.$$

这正是实现中小规模检验值对应的结果。

代码如何工作

C++、Python 和 Java 实现采用同样的流程。首先生成需要的 Fibonacci 数。对于每个 \((p,q)\),先求出 \(\delta\)、\(\sin\delta\)、\(\cos\delta\) 与 \(\tan\delta\)。然后内层循环从 \(k=2\) 走到 \(q\),用上面的递推公式推进 \(\sin(k\delta)\) 和 \(\cos(k\delta)\),构造比值 \(\sin\delta/(\cos((k-1)\delta)\cos(k\delta))\),乘上交替符号,并把它加入一个带补偿的运行和中。

内层结束后,再减去 \(\tan\delta\),乘上 \(p(-1)^q\),就得到该参数对对应的面积。外层对所有 Fibonacci 参数对的总和同样使用补偿求和,因为很多项会出现符号相反且数值接近的抵消。最后结果以 10 位小数格式输出。

复杂度分析

单次 \(\mathcal{A}(p,q)\) 的计算需要 \(O(q)\) 次算术操作和 \(O(1)\) 额外空间。对整个题目范围而言,总时间复杂度为

$$O\left(\sum_{m=4}^{35}F_{m-2}\right)=O(F_{35}),$$

这是一个固定且完全可控的规模。若按精确次数计算,内层循环总共执行

$$\sum_{j=2}^{33}F_j=F_{35}-2=9{,}227{,}463$$

次。除了一张很短的 Fibonacci 表之外,额外空间始终保持在 \(O(1)\)。

脚注与参考资料

  1. 题目页面: https://projecteuler.net/problem=841
  2. 规则星形多边形: Wikipedia - 星形多边形
  3. 三角恒等式: Wikipedia - 三角恒等式
  4. Fibonacci 数: Wikipedia - 斐波那契数
  5. Kahan 补偿求和: Wikipedia - Kahan summation algorithm

Краткое описание задачи

Для каждой подходящей пары \((p,q)\) требуется вычислить ориентированную площадь правильного звёздчатого многоугольника с \(p\)-кратной симметрией и шаговым параметром \(q\), а затем просуммировать эти значения по семейству пар, построенному из чисел Фибоначчи. Реализации на C++, Python и Java не строят фигуру по вершинам и не ищут явно все точки пересечения. Вместо этого они используют тригонометрическую формулу для одного повторяющегося секторного вклада и затем масштабируют результат с помощью симметрии.

Если \(F_1=F_2=1\), то фактически вычисляется сумма по парам \((F_m,F_{m-2})\) при \(m=4,5,\dots,35\). Следовательно, задача сводится не к прямому геометрическому моделированию, а к устойчивому вычислению серии тригонометрических сумм.

Математический подход

Обозначим через \(\mathcal{A}(p,q)\) ориентированную площадь, которую считают реализации. Основная идея состоит в том, чтобы свести регулярную геометрию к одному базовому углу и затем упростить возникающие выражения с помощью тождеств для тангенса.

Шаг 1: Ввести базовый угол

Для правильной фигуры с \(p\)-кратной симметрией естественная угловая единица равна

$$\delta=\frac{\pi}{p}.$$

Далее используются углы

$$\theta_k=k\delta \qquad (k\ge 1).$$

Вместо того чтобы выписывать все декартовы координаты, решение выражает площадь напрямую через \(\sin(\theta_k)\), \(\cos(\theta_k)\) и \(\tan(\theta_k)\). Этого достаточно, потому что каждый локальный вклад зависит только от соседних углов \((k-1)\delta\) и \(k\delta\).

Шаг 2: Превратить локальный вклад в разность тангенсов

Базовое выражение в реализациях имеет вид

$$\frac{\sin\delta}{\cos((k-1)\delta)\cos(k\delta)}.$$

Используем стандартное тождество

$$\tan u-\tan v=\frac{\sin(u-v)}{\cos u\cos v}.$$

Если положить \(u=k\delta\) и \(v=(k-1)\delta\), то \(u-v=\delta\), поэтому

$$\frac{\sin\delta}{\cos((k-1)\delta)\cos(k\delta)}=\tan(k\delta)-\tan((k-1)\delta).$$

После этого геометрическая задача превращается в сумму первых разностей тангенса. Значит, можно обойтись без явного вычисления пересечений и без реконструкции всей фигуры.

Шаг 3: Построить знакопеременную секторную сумму

Реализации считают сумму

$$T(p,q)=\sum_{k=2}^{q}(-1)^k\frac{\sin\delta}{\cos((k-1)\delta)\cos(k\delta)}.$$

С учётом предыдущего шага это то же самое, что

$$T(p,q)=\sum_{k=2}^{q}(-1)^k\left(\tan(k\delta)-\tan((k-1)\delta)\right).$$

Итоговая формула площади имеет вид

$$\mathcal{A}(p,q)=p(-1)^q\left(T(p,q)-\tan\delta\right).$$

Множитель \(p\) отражает \(p\)-кратную вращательную симметрию: найдя вклад одного представительного сектора, мы получаем всю площадь повторением этого вклада \(p\) раз. Знаки внутри суммы и внешний множитель \((-1)^q\) задают выбранную ориентацию.

Шаг 4: Продвигать углы рекуррентно

Было бы лишним вычислять \(\sin(k\delta)\) и \(\cos(k\delta)\) заново на каждом шаге. Поэтому реализации используют формулы сложения:

$$\sin((k+1)\delta)=\sin(k\delta)\cos\delta+\cos(k\delta)\sin\delta,$$

$$\cos((k+1)\delta)=\cos(k\delta)\cos\delta-\sin(k\delta)\sin\delta.$$

После начального вычисления \(\sin\delta\) и \(\cos\delta\) все последующие углы порождаются рекуррентно. Именно так устроен внутренний цикл программы.

Шаг 5: Внешняя сумма по парам Фибоначчи

Построенная последовательность Фибоначчи начинается так:

$$1,1,2,3,5,8,\dots$$

и реализации берут пары элементов, отстоящих на две позиции. В стандартной записи получается

$$\sum_{m=4}^{35}\mathcal{A}(F_m,F_{m-2}).$$

Эта индексация важна: вычисление идёт не по произвольным парам Фибоначчи, а ровно по указанному конечному набору входов.

Разобранный пример: \(\mathcal{A}(8,3)\)

Пусть \(p=8\) и \(q=3\). Тогда

$$\delta=\frac{\pi}{8},\qquad \tan\delta=\sqrt{2}-1,\qquad \tan(2\delta)=1,\qquad \tan(3\delta)=\sqrt{2}+1.$$

Во внутренней знакопеременной сумме только два слагаемых:

$$\begin{aligned} T(8,3) &=\left(\tan\frac{\pi}{4}-\tan\frac{\pi}{8}\right)-\left(\tan\frac{3\pi}{8}-\tan\frac{\pi}{4}\right)\\ &=\left(1-(\sqrt{2}-1)\right)-\left((\sqrt{2}+1)-1\right)\\ &=2-2\sqrt{2}. \end{aligned}$$

Далее вычитается базовый член:

$$T(8,3)-\tan\delta=(2-2\sqrt{2})-(\sqrt{2}-1)=3-3\sqrt{2}.$$

Так как \(q=3\) нечётно, \((-1)^q=-1\). Следовательно,

$$\mathcal{A}(8,3)=8(-1)(3-3\sqrt{2})=24(\sqrt{2}-1)\approx 9.9411254970.$$

Это точно совпадает с малой числовой проверкой, которую воспроизводят реализации.

Как работает код

Реализации на C++, Python и Java устроены одинаково. Сначала строятся нужные числа Фибоначчи. Для каждой пары \((p,q)\) вычисляются \(\delta\), \(\sin\delta\), \(\cos\delta\) и \(\tan\delta\). Затем внутренний цикл по \(k=2,3,\dots,q\) рекуррентно обновляет \(\sin(k\delta)\) и \(\cos(k\delta)\), формирует дробь \(\sin\delta/(\cos((k-1)\delta)\cos(k\delta))\), применяет чередующийся знак и добавляет результат в компенсированную накопительную сумму.

После завершения внутреннего цикла из суммы вычитается \(\tan\delta\), результат умножается на \(p(-1)^q\), и получается одна площадь. Внешняя сумма по всем парам Фибоначчи также накапливается с компенсацией, поскольку многие слагаемые имеют разные знаки и близкие величины. В конце ответ выводится с точностью до 10 знаков после запятой.

Анализ сложности

Одно вычисление \(\mathcal{A}(p,q)\) требует \(O(q)\) арифметических действий и \(O(1)\) дополнительной памяти. Для всего диапазона задачи итоговая трудоёмкость равна

$$O\left(\sum_{m=4}^{35}F_{m-2}\right)=O(F_{35}),$$

то есть это фиксированный и вполне умеренный объём работы. Точное число проходов внутреннего цикла равно

$$\sum_{j=2}^{33}F_j=F_{35}-2=9{,}227{,}463.$$

Память остаётся \(O(1)\), если не считать короткий массив чисел Фибоначчи.

Сноски и ссылки

  1. Страница задачи: https://projecteuler.net/problem=841
  2. Звёздчатые многоугольники: Wikipedia - Звёздчатый многоугольник
  3. Тригонометрические тождества: Wikipedia - Тригонометрия
  4. Числа Фибоначчи: Wikipedia - Числа Фибоначчи
  5. Алгоритм суммирования Кэхэна: Wikipedia - Kahan summation algorithm

ملخص المسألة

لكل زوج مناسب \((p,q)\)، المطلوب هو حساب المساحة الموجهة لمضلع نجمي منتظم له تناظر دوراني من الرتبة \(p\) ومعامل خطوة \(q\)، ثم جمع هذه القيم على عائلة من الأزواج مبنية على أعداد فيبوناتشي. تنفيذات ++C وPython وJava لا تبني الشكل رأسًا برأس ولا تحسب نقاط تقاطع المستقيمات بشكل صريح. بدلًا من ذلك، تستعمل صيغة مثلثية لقطاع واحد متكرر ثم توسعها إلى الشكل كله بالاعتماد على التناظر.

إذا كتبنا \(F_1=F_2=1\)، فإن المجموع النهائي يُحسب على الأزواج \((F_m,F_{m-2})\) عندما يكون \(m=4,5,\dots,35\). لذلك فجوهر المسألة ليس محاكاة هندسية مباشرة، بل تحويل مساحة كل مضلع نجمي إلى مجموع أحادي البعد مستقر عدديًا.

المنهج الرياضي

لنرمز إلى كمية المساحة الموجهة التي تعتمدها التنفيذات بالرمز \(\mathcal{A}(p,q)\). الفكرة الأساسية هي اختزال البنية المنتظمة إلى زاوية أساسية واحدة، ثم تبسيط الحدود الناتجة بواسطة متطابقات الظل.

الخطوة 1: تحديد الزاوية الأساسية

بالنسبة إلى شكل منتظم ذي تناظر من الرتبة \(p\)، تكون وحدة الزاوية الطبيعية هي

$$\delta=\frac{\pi}{p}.$$

وتعمل التنفيذات على المتتالية

$$\theta_k=k\delta \qquad (k\ge 1).$$

بدل تتبع جميع الإحداثيات الديكارتية، يجري التعبير عن الإسهامات المساحية مباشرة باستعمال \(\sin(\theta_k)\) و\(\cos(\theta_k)\) و\(\tan(\theta_k)\). هذا يكفي لأن كل مساهمة محلية تعتمد فقط على الزاويتين المتتاليتين \((k-1)\delta\) و\(k\delta\).

الخطوة 2: تحويل الحد المحلي إلى فرق بين ظلين

اللبنة الأساسية المتكررة في التنفيذات هي

$$\frac{\sin\delta}{\cos((k-1)\delta)\cos(k\delta)}.$$

نستخدم الآن المتطابقة القياسية

$$\tan u-\tan v=\frac{\sin(u-v)}{\cos u\cos v}.$$

وباختيار \(u=k\delta\) و\(v=(k-1)\delta\) نحصل على \(u-v=\delta\)، ومن ثم

$$\frac{\sin\delta}{\cos((k-1)\delta)\cos(k\delta)}=\tan(k\delta)-\tan((k-1)\delta).$$

هذه الخطوة مهمة لأنها تحول الهندسة إلى مجموع فروق أولى لقيم الظل، من غير حاجة إلى حل تقاطعات أو إعادة بناء الشكل كاملًا.

الخطوة 3: بناء مجموع القطاعات مع الإشارة

تحسب التنفيذات المجموع المتناوب

$$T(p,q)=\sum_{k=2}^{q}(-1)^k\frac{\sin\delta}{\cos((k-1)\delta)\cos(k\delta)}.$$

وباستخدام الخطوة السابقة يمكن كتابته على الصورة المكافئة

$$T(p,q)=\sum_{k=2}^{q}(-1)^k\left(\tan(k\delta)-\tan((k-1)\delta)\right).$$

ثم تكون صيغة المساحة النهائية

$$\mathcal{A}(p,q)=p(-1)^q\left(T(p,q)-\tan\delta\right).$$

يعكس العامل \(p\) وجود تناظر دوراني من الرتبة \(p\): فإذا عُرفت مساهمة قطاع ممثل واحد أمكن الحصول على الشكل كله بتكرارها \(p\) مرة. أما الإشارات المتناوبة والعامل الخارجي \((-1)^q\) فيمثلان اصطلاح الاتجاه في الصيغة.

الخطوة 4: تحديث الزوايا بعلاقة عودية

ليس من الضروري إعادة حساب \(\sin(k\delta)\) و\(\cos(k\delta)\) من الصفر عند كل خطوة. لذلك تستعمل التنفيذات صيغ الجمع

$$\sin((k+1)\delta)=\sin(k\delta)\cos\delta+\cos(k\delta)\sin\delta,$$

$$\cos((k+1)\delta)=\cos(k\delta)\cos\delta-\sin(k\delta)\sin\delta.$$

وهكذا، بعد حساب \(\sin\delta\) و\(\cos\delta\) مرة واحدة، يمكن توليد الزوايا التالية تكراريًا. هذا يطابق تمامًا ما يجري داخل الحلقة الداخلية في التنفيذ.

الخطوة 5: الجمع الخارجي على أزواج فيبوناتشي

متتالية فيبوناتشي التي تُبنى في التنفيذ تبدأ هكذا:

$$1,1,2,3,5,8,\dots$$

ثم تؤخذ أزواج تفصل بينها خانتان. وبالترميز القياسي يصبح المجموع الكلي

$$\sum_{m=4}^{35}\mathcal{A}(F_m,F_{m-2}).$$

هذا التفصيل مهم، لأنه يحدد بدقة كيف تُختار المدخلات: ليست أزواجًا عشوائية من فيبوناتشي، بل هذه القائمة الثابتة بالضبط.

مثال محلول: \(\mathcal{A}(8,3)\)

عندما \(p=8\) و\(q=3\)، يكون

$$\delta=\frac{\pi}{8},\qquad \tan\delta=\sqrt{2}-1,\qquad \tan(2\delta)=1,\qquad \tan(3\delta)=\sqrt{2}+1.$$

يحتوي المجموع الداخلي المتناوب على حدين فقط:

$$\begin{aligned} T(8,3) &=\left(\tan\frac{\pi}{4}-\tan\frac{\pi}{8}\right)-\left(\tan\frac{3\pi}{8}-\tan\frac{\pi}{4}\right)\\ &=\left(1-(\sqrt{2}-1)\right)-\left((\sqrt{2}+1)-1\right)\\ &=2-2\sqrt{2}. \end{aligned}$$

بعد ذلك نطرح الحد الأساسي الإضافي:

$$T(8,3)-\tan\delta=(2-2\sqrt{2})-(\sqrt{2}-1)=3-3\sqrt{2}.$$

وبما أن \(q=3\) فردي، فإن \((-1)^q=-1\). إذن

$$\mathcal{A}(8,3)=8(-1)(3-3\sqrt{2})=24(\sqrt{2}-1)\approx 9.9411254970.$$

وهذه هي القيمة العددية الصغيرة التي تعيدها التنفيذات عند التحقق من الصيغة.

كيف يعمل الكود

تتبع تنفيذات ++C وPython وJava البنية نفسها. أولًا تُولَّد قيم فيبوناتشي المطلوبة. ولكل زوج \((p,q)\)، تُحسب \(\delta\) و\(\sin\delta\) و\(\cos\delta\) و\(\tan\delta\). بعد ذلك تسير الحلقة الداخلية من \(k=2\) حتى \(q\)، وتحدّث \(\sin(k\delta)\) و\(\cos(k\delta)\) بالعلاقة العودية السابقة، ثم تكوّن الكسر \(\sin\delta/(\cos((k-1)\delta)\cos(k\delta))\)، وتطبق الإشارة المتناوبة، وتضيف النتيجة إلى مجموع جارٍ مع تعويض عددي.

بعد انتهاء الحلقة الداخلية، يطرح التنفيذ \(\tan\delta\)، ثم يضرب الناتج في \(p(-1)^q\) للحصول على مساحة واحدة. كما يُجمع المجموع الخارجي على جميع أزواج فيبوناتشي باستعمال جمع تعويضي أيضًا، لأن كثيرًا من الحدود متقاربة المقدار ومتعاكسة الإشارة. وفي النهاية تُطبع النتيجة بدقة 10 منازل عشرية.

تحليل التعقيد

يتطلب حساب واحد لـ \(\mathcal{A}(p,q)\) عددًا قدره \(O(q)\) من العمليات الحسابية وذاكرة إضافية مقدارها \(O(1)\). وعلى المجال الكامل للمسألة يكون الزمن الكلي

$$O\left(\sum_{m=4}^{35}F_{m-2}\right)=O(F_{35}),$$

وهو حمل ثابت ومقبول جدًا. وإذا عُدَّت التكرارات بدقة، فإن الحلقة الداخلية تنفذ ما مجموعه

$$\sum_{j=2}^{33}F_j=F_{35}-2=9{,}227{,}463$$

مرة. أما الذاكرة فتبقى \(O(1)\) باستثناء جدول فيبوناتشي القصير.

حواشٍ ومراجع

  1. صفحة المسألة: https://projecteuler.net/problem=841
  2. المضلعات النجمية المنتظمة: Wikipedia - مضلع نجمي
  3. المتطابقات المثلثية: Wikipedia - متطابقة مثلثية
  4. أعداد فيبوناتشي: Wikipedia - متتالية فيبوناتشي
  5. خوارزمية جمع Kahan: Wikipedia - Kahan summation algorithm