An Alexandrian integer is a positive integer obtained from an integer triple satisfying
$$\frac{1}{x}+\frac{1}{y}+\frac{1}{z}=\frac{1}{xyz}.$$
For positive Alexandrian values one may choose the generating triple with exactly one negative entry, and the reported number is \(A=\lvert xyz\rvert\). Problem 221 asks for the \(150000\)-th term when all such positive integers are listed in increasing order.
The crucial point is that the search is not over arbitrary triples. The reciprocal identity collapses to a rigid divisor condition, so every valid Alexandrian integer comes from factoring a number of the form \(p^2+1\). That is the mathematical reason the implementations can solve the problem without brute-forcing three independent variables.
The derivation used by the implementations is a complete parameterization of the Alexandrian integers that can appear in the ordered sequence.
Take a valid triple in the form \((-p,q,r)\) with \(p,q,r>0\). Substituting it into the defining identity gives
$$-\frac{1}{p}+\frac{1}{q}+\frac{1}{r}=\frac{1}{(-p)qr}=-\frac{1}{pqr}.$$
Multiplying by \(pqr\) removes the denominators and leaves the Diophantine equation
$$qr-pq-pr=1.$$
So the reciprocal statement is equivalent to a very structured bilinear equation in the three integers.
Add \(p^2\) to both sides of the previous relation:
$$qr-pq-pr+p^2=p^2+1.$$
The left-hand side factors immediately:
$$(q-p)(r-p)=p^2+1.$$
Now set
$$d=q-p,\qquad e=r-p.$$
Then \(de=p^2+1\). Moreover \(d\) and \(e\) must be positive. If, for example, \(q\le p\), then \(qr-pq-pr\le pr-pq-pr=-pq\lt 0\), contradicting \(qr-pq-pr=1\). Therefore every valid triple is of the form
$$(-p,\;p+d,\;p+e)\qquad\text{with}\qquad de=p^2+1.$$
The corresponding Alexandrian integer is
$$A=\lvert (-p)(p+d)(p+e)\rvert=p(p+d)(p+e).$$
The converse is just as important: if \(p\ge 1\) and \(d,e\) are positive divisors with \(de=p^2+1\), then \((-p,p+d,p+e)\) satisfies the defining identity. So this is not merely a source of examples; it is the full classification exploited by the code.
Once \(p\) is fixed, the only freedom is the divisor pair \((d,e)\) of \(p^2+1\). Swapping the two factors does not change the product, because
$$p(p+d)(p+e)=p(p+e)(p+d).$$
Hence it is enough to enumerate divisors \(d\le \sqrt{p^2+1}\) and recover the partner \(e=(p^2+1)/d\). This removes the trivial mirror duplication coming from \((d,e)\) and \((e,d)\).
For \(p=3\) we have
$$p^2+1=10.$$
The divisor pairs are \((1,10)\) and \((2,5)\). They produce the triples
$$(-3,4,13)\qquad\text{and}\qquad(-3,5,8),$$
so the corresponding Alexandrian integers are
$$3\cdot 4\cdot 13=156,\qquad 3\cdot 5\cdot 8=120.$$
Indeed,
$$-\frac{1}{3}+\frac{1}{4}+\frac{1}{13}=-\frac{1}{156},\qquad -\frac{1}{3}+\frac{1}{5}+\frac{1}{8}=-\frac{1}{120}.$$
This example explains two implementation choices. A single value of \(p\) can generate several Alexandrian integers, and those values do not arrive in globally sorted order. The search therefore streams candidates into a structure that keeps only the smallest values seen so far.
For every future parameter \(p'\) and every admissible divisor pair, we always have \(d\ge 1\) and \(e\ge 1\). Therefore every unseen candidate obeys
$$A'=p'(p'+d)(p'+e)\ge p'(p'+1)^2.$$
After all candidates for a given \(p\) have been processed, every later parameter \(p+1,p+2,\dots\) satisfies
$$A'\ge (p+1)(p+2)^2.$$
If the container holding the current smallest \(k\) candidates is already full and this lower bound is larger than its maximum element, then no future value can enter the smallest \(k\). At that point the search may stop, and the current maximum is exactly the \(k\)-th Alexandrian integer.
The C++, Python, and Java implementations iterate upward over \(p=1,2,3,\dots\). For each \(p\), they form \(n=p^2+1\), enlarge an incremental prime table just enough to factor \(n\), and then recursively generate all divisors \(d\le \sqrt{n}\). Each such divisor determines the complementary divisor \(e=n/d\) and therefore one candidate \(A=p(p+d)(p+e)\).
Instead of storing every candidate ever seen, the implementations maintain a max-heap of fixed size \(k\). While that heap is not yet full, every new unique candidate is inserted. Once it is full, only candidates smaller than the current heap maximum can matter; larger values are discarded immediately. A companion hash set tracks the values currently present in the heap so that equal Alexandrian integers are not counted twice.
The three versions differ mainly in numeric representation, not in mathematics. The C++ implementation uses 128-bit arithmetic for the products, the Python implementation relies on arbitrary-precision integers, and the Java implementation uses big integers. After each completed value of \(p\), they apply the lower-bound test above. When that test proves that no later \(p\) can improve the heap, the current heap maximum is returned.
Let \(P\) be the last parameter examined before the stopping criterion succeeds, let \(\tau(n)\) be the divisor-counting function, and let \(\pi(P)\) denote the number of stored primes up to \(P\). For each \(p\le P\), the algorithm factors \(p^2+1\) by trial division through the current prime table and then enumerates the relevant divisors. A faithful high-level bound is
$$T(P)=O\!\left(\sum_{p=1}^{P}\bigl(\pi(p)+\tau(p^2+1)\log k\bigr)\right).$$
The \(\pi(p)\) term reflects prime testing up to roughly \(\sqrt{p^2+1}\), and the \(\log k\) factor comes from possible heap updates when a candidate is admitted into the current best \(k\).
Memory usage is
$$O\bigl(k+\pi(P)+\max_{p\le P}\tau(p^2+1)\bigr).$$
The dominant stored objects are the bounded heap, the hash set of active values, the growing prime table, and a temporary divisor buffer for the current factorization. The whole method is efficient because it replaces a three-variable search with a one-parameter scan, divisor generation, and aggressive early stopping.
Eine Alexandrian-Zahl ist eine positive ganze Zahl, die aus einem ganzzahligen Tripel mit der Identität
$$\frac{1}{x}+\frac{1}{y}+\frac{1}{z}=\frac{1}{xyz}$$
entsteht. Für positive Alexandrian-Zahlen kann man das erzeugende Tripel so wählen, dass genau ein Eintrag negativ ist; die gesuchte Zahl ist dann \(A=\lvert xyz\rvert\). In Problem 221 soll das \(150000\)-te Glied der aufsteigend sortierten Folge aller solchen positiven Zahlen bestimmt werden.
Der entscheidende Punkt ist, dass man nicht über beliebige Tripel suchen muss. Die Kehrwertgleichung fällt auf eine starre Teilerbedingung zurück, sodass jede gültige Alexandrian-Zahl aus der Faktorisierung einer Zahl der Form \(p^2+1\) stammt. Genau diese Struktur macht den Algorithmus praktikabel.
Die Implementierungen benutzen eine vollständige Parametrisierung aller Alexandrian-Zahlen, die in der sortierten Folge auftreten können.
Nehmen wir ein gültiges Tripel in der Form \((-p,q,r)\) mit \(p,q,r>0\). Setzt man es in die definierende Identität ein, erhält man
$$-\frac{1}{p}+\frac{1}{q}+\frac{1}{r}=\frac{1}{(-p)qr}=-\frac{1}{pqr}.$$
Nach Multiplikation mit \(pqr\) bleiben keine Nenner mehr übrig, und es entsteht die diophantische Gleichung
$$qr-pq-pr=1.$$
Die ursprüngliche Kehrwertaussage ist also äquivalent zu einer sehr starren bilinearen Beziehung zwischen den drei ganzen Zahlen.
Addiert man \(p^2\) auf beiden Seiten, so folgt
$$qr-pq-pr+p^2=p^2+1.$$
Die linke Seite faktorisiert sofort zu
$$(q-p)(r-p)=p^2+1.$$
Setzt man nun
$$d=q-p,\qquad e=r-p,$$
dann gilt \(de=p^2+1\). Außerdem müssen \(d\) und \(e\) positiv sein. Wäre etwa \(q\le p\), dann wäre \(qr-pq-pr\le pr-pq-pr=-pq\lt 0\), im Widerspruch zu \(qr-pq-pr=1\). Also hat jedes gültige Tripel die Form
$$(-p,\;p+d,\;p+e)\qquad\text{mit}\qquad de=p^2+1.$$
Die zugehörige Alexandrian-Zahl lautet
$$A=\lvert (-p)(p+d)(p+e)\rvert=p(p+d)(p+e).$$
Ebenso wichtig ist die Umkehrung: Sind \(p\ge 1\) und \(d,e\) positive Teiler mit \(de=p^2+1\), dann erfüllt \((-p,p+d,p+e)\) die definierende Identität. Das ist also nicht nur eine Quelle von Beispielen, sondern die vollständige Klassifikation, auf der der Code basiert.
Ist \(p\) fest, dann bleibt nur noch die Wahl eines Teilerpaars \((d,e)\) von \(p^2+1\). Vertauscht man die beiden Faktoren, ändert sich das Produkt nicht, denn
$$p(p+d)(p+e)=p(p+e)(p+d).$$
Daher genügt es, alle Teiler \(d\le \sqrt{p^2+1}\) zu erzeugen und den Partner \(e=(p^2+1)/d\) zu ergänzen. So vermeidet man die triviale Spiegel-Duplikation der Paare \((d,e)\) und \((e,d)\).
Für \(p=3\) gilt
$$p^2+1=10.$$
Die Teilerpaare sind \((1,10)\) und \((2,5)\). Daraus entstehen die Tripel
$$(-3,4,13)\qquad\text{und}\qquad(-3,5,8),$$
also die Alexandrian-Zahlen
$$3\cdot 4\cdot 13=156,\qquad 3\cdot 5\cdot 8=120.$$
Tatsächlich gilt
$$-\frac{1}{3}+\frac{1}{4}+\frac{1}{13}=-\frac{1}{156},\qquad -\frac{1}{3}+\frac{1}{5}+\frac{1}{8}=-\frac{1}{120}.$$
Dieses Beispiel erklärt zwei wichtige Implementationsdetails. Ein einziges \(p\) kann mehrere Alexandrian-Zahlen liefern, und diese Werte erscheinen nicht automatisch in global sortierter Reihenfolge. Deshalb werden die Kandidaten in eine Struktur gestreamt, die nur die bislang kleinsten Werte festhält.
Für jeden zukünftigen Parameter \(p'\) und jedes zulässige Teilerpaar gilt stets \(d\ge 1\) und \(e\ge 1\). Damit erfüllt jeder noch nicht gesehene Kandidat
$$A'=p'(p'+d)(p'+e)\ge p'(p'+1)^2.$$
Nachdem alle Kandidaten zu einem gegebenen \(p\) verarbeitet wurden, gilt für jeden späteren Parameter \(p+1,p+2,\dots\)
$$A'\ge (p+1)(p+2)^2.$$
Ist der Behälter mit den aktuell kleinsten \(k\) Kandidaten bereits voll und liegt diese Schranke schon über seinem größten Element, dann kann kein zukünftiger Wert mehr in die kleinsten \(k\) hineinfallen. Genau dann darf die Suche enden, und das aktuelle Maximum ist die gesuchte \(k\)-te Alexandrian-Zahl.
Die C++-, Python- und Java-Implementierungen laufen \(p=1,2,3,\dots\) nach oben durch. Für jedes \(p\) bilden sie \(n=p^2+1\), erweitern eine inkrementell aufgebaute Primtabelle gerade weit genug zur Faktorisierung von \(n\) und erzeugen dann rekursiv alle Teiler \(d\le \sqrt{n}\). Jeder solche Teiler bestimmt den Ergänzungsteiler \(e=n/d\) und damit genau einen Kandidaten \(A=p(p+d)(p+e)\).
Statt alle jemals gesehenen Kandidaten zu speichern, halten die Implementierungen einen Max-Heap fester Größe \(k\). Solange dieser Heap noch nicht gefüllt ist, wird jeder neue eindeutige Kandidat eingefügt. Danach sind nur noch Kandidaten relevant, die kleiner als das aktuelle Heap-Maximum sind; größere Werte werden sofort verworfen. Ein zusätzliches Hash-Set merkt sich die aktuell im Heap liegenden Werte, damit gleiche Alexandrian-Zahlen nicht doppelt gezählt werden.
Die drei Versionen unterscheiden sich hauptsächlich in der Zahlenrepräsentation, nicht in der Mathematik. C++ verwendet 128-Bit-Arithmetik für die Produkte, Python beliebig große ganze Zahlen und Java große Ganzzahlen. Nach jedem vollständig bearbeiteten \(p\) wird die obige untere Schranke geprüft. Sobald sie zeigt, dass kein späteres \(p\) den Heap noch verbessern kann, wird dessen aktuelles Maximum zurückgegeben.
Sei \(P\) der letzte untersuchte Parameter vor dem erfolgreichen Abbruchkriterium, \(\tau(n)\) die Teileranzahl-Funktion und \(\pi(P)\) die Anzahl der bis \(P\) gespeicherten Primzahlen. Für jedes \(p\le P\) faktorisiert der Algorithmus \(p^2+1\) per Probedivision durch die vorhandene Primtabelle und erzeugt anschließend die relevanten Teiler. Eine treffende Obergrenze auf hohem Niveau ist
$$T(P)=O\!\left(\sum_{p=1}^{P}\bigl(\pi(p)+\tau(p^2+1)\log k\bigr)\right).$$
Der Term \(\pi(p)\) modelliert die Primtests bis ungefähr \(\sqrt{p^2+1}\), und der Faktor \(\log k\) stammt von möglichen Heap-Operationen, wenn ein Kandidat in die aktuelle Bestliste aufgenommen wird.
Der Speicherbedarf ist
$$O\bigl(k+\pi(P)+\max_{p\le P}\tau(p^2+1)\bigr).$$
Gespeichert werden im Wesentlichen der begrenzte Heap, das Hash-Set der aktiven Werte, die wachsende Primtabelle und ein temporärer Teilerpuffer für die aktuelle Faktorisierung. Effizient wird das Verfahren dadurch, dass eine Suche in drei Variablen auf einen eindimensionalen Durchlauf mit Teilererzeugung und frühem Abbruch reduziert wird.
Bir Alexandrian tamsayısı,
$$\frac{1}{x}+\frac{1}{y}+\frac{1}{z}=\frac{1}{xyz}$$
eşitliğini sağlayan bir tam sayı üçlüsünden elde edilen pozitif bir sayıdır. Pozitif Alexandrian değerler için üretici üçlü tam olarak bir negatif terim içerecek biçimde seçilebilir; bu durumda raporlanan sayı \(A=\lvert xyz\rvert\) olur. Problem 221, bu tür tüm pozitif sayıların artan sıralamasındaki \(150000\). terimi ister.
Kritik nokta, aramanın keyfi üçlüler üzerinde yapılmamasıdır. Bu terslik özdeşliği çok katı bir bölen koşuluna indirgenir; dolayısıyla her geçerli Alexandrian tamsayısı \(p^2+1\) biçimindeki bir sayının çarpanlarına ayrılmasından doğar. Uygulamaların üç bağımsız değişken üzerinde kaba kuvvet kullanmadan çalışabilmesinin nedeni budur.
Uygulamaların kullandığı türetim, sıralı dizide ortaya çıkabilecek tüm Alexandrian tamsayılarını eksiksiz biçimde parametrize eder.
Geçerli bir üçlüyü \((-p,q,r)\) biçiminde alalım; burada \(p,q,r>0\). Bunu tanımdaki eşitliğe yerleştirince
$$-\frac{1}{p}+\frac{1}{q}+\frac{1}{r}=\frac{1}{(-p)qr}=-\frac{1}{pqr}$$
elde edilir. Her iki tarafı \(pqr\) ile çarpınca paydalar kaybolur ve şu Diophantine denklem kalır:
$$qr-pq-pr=1.$$
Böylece üç karşılıklı kesrin verdiği ifade, son derece yapılandırılmış bir bilineer eşitliğe dönüşür.
Bir önceki eşitliğin iki tarafına da \(p^2\) ekleyelim:
$$qr-pq-pr+p^2=p^2+1.$$
Sol taraf hemen çarpanlara ayrılır:
$$(q-p)(r-p)=p^2+1.$$
Şimdi
$$d=q-p,\qquad e=r-p$$
tanımlarını yapalım. Böylece \(de=p^2+1\) olur. Üstelik \(d\) ve \(e\) pozitiftir. Örneğin \(q\le p\) olsaydı \(qr-pq-pr\le pr-pq-pr=-pq\lt 0\) çıkardı; bu da \(qr-pq-pr=1\) ile çelişir. Demek ki her geçerli üçlü
$$(-p,\;p+d,\;p+e)\qquad\text{ve}\qquad de=p^2+1$$
şeklindedir. Buna karşılık gelen Alexandrian tamsayısı da
$$A=\lvert (-p)(p+d)(p+e)\rvert=p(p+d)(p+e)$$
olur. Ters yön de aynı derecede önemlidir: \(p\ge 1\) ve \(de=p^2+1\) olacak biçimde pozitif bölenler \(d,e\) seçilirse \((-p,p+d,p+e)\) tanımdaki özdeşliği sağlar. Yani bu yalnızca örnek üreten bir formül değil, kodun kullandığı tam sınıflandırmadır.
\(p\) sabitlendiğinde geriye kalan tek seçim \(p^2+1\)'in bölen çifti \((d,e)\) olur. Bu iki çarpanı yer değiştirmenin ürünü değiştirmediği açıktır:
$$p(p+d)(p+e)=p(p+e)(p+d).$$
Bu yüzden yalnızca \(d\le \sqrt{p^2+1}\) koşulunu sağlayan bölenleri üretmek ve eş böleni \(e=(p^2+1)/d\) ile tamamlamak yeterlidir. Böylece \((d,e)\) ile \((e,d)\) çiftlerinden doğan simetrik tekrarlar önlenir.
\(p=3\) için
$$p^2+1=10$$
olur. Bölen çiftleri \((1,10)\) ve \((2,5)\) olduğundan şu üçlüler elde edilir:
$$(-3,4,13)\qquad\text{ve}\qquad(-3,5,8).$$
Bunların ürettiği Alexandrian tamsayıları
$$3\cdot 4\cdot 13=156,\qquad 3\cdot 5\cdot 8=120$$
şeklindedir. Nitekim
$$-\frac{1}{3}+\frac{1}{4}+\frac{1}{13}=-\frac{1}{156},\qquad -\frac{1}{3}+\frac{1}{5}+\frac{1}{8}=-\frac{1}{120}.$$
Bu örnek iki önemli uygulama kararını açıklar. Tek bir \(p\) değeri birden fazla Alexandrian tamsayısı üretebilir ve bu sayılar küresel olarak sıralı gelmez. Bu nedenle adaylar, o ana kadar görülen en küçük değerleri tutan bir yapıya akıtılır.
Her gelecekteki \(p'\) parametresi ve her geçerli bölen çifti için daima \(d\ge 1\) ve \(e\ge 1\) vardır. Dolayısıyla henüz görülmemiş her aday
$$A'=p'(p'+d)(p'+e)\ge p'(p'+1)^2$$
eşitsizliğini sağlar. Verilen bir \(p\) için bütün adaylar işlendiğinde, sonraki tüm parametreler \(p+1,p+2,\dots\) için
$$A'\ge (p+1)(p+2)^2$$
geçerlidir. Eğer o anda elde tutulan en küçük \(k\) adaydan oluşan yapı doluysa ve bu alt sınır yapıdaki en büyük elemandan da büyükse, ileride gelecek hiçbir değer ilk \(k\)'ya giremez. Tam bu noktada arama durabilir; mevcut maksimum tam olarak \(k\). Alexandrian tamsayısıdır.
C++, Python ve Java uygulamaları \(p=1,2,3,\dots\) üzerinden artan biçimde ilerler. Her \(p\) için önce \(n=p^2+1\) oluşturulur, sonra \(n\)'i çarpanlara ayırmaya yetecek kadar büyütülen artımlı bir asal tablosu kullanılır ve \(d\le \sqrt{n}\) olan tüm bölenler özyinelemeli biçimde üretilir. Her böyle \(d\), tamamlayıcı bölen \(e=n/d\) ile birlikte bir aday \(A=p(p+d)(p+e)\) verir.
Tüm adayları sonsuza kadar saklamak yerine uygulamalar sabit boyutlu bir max-heap tutar. Heap henüz dolu değilse her yeni benzersiz aday eklenir. Heap dolduktan sonra yalnızca mevcut en büyük heap elemanından daha küçük adaylar önemli olabilir; daha büyük değerler anında atılır. Heap içinde o anda bulunan değerleri izleyen bir hash set de aynı Alexandrian tamsayısının iki kez sayılmasını engeller.
Üç sürüm arasındaki fark esas olarak sayı gösterimindedir, matematikte değil. C++ çarpımlar için 128 bit aritmetik kullanır, Python keyfi büyüklükte tamsayılara güvenir, Java ise büyük tamsayılar kullanır. Her tamamlanmış \(p\) adımından sonra yukarıdaki alt sınır testi uygulanır. Bu test artık daha sonraki hiçbir \(p\)'nin heap'i iyileştiremeyeceğini gösterdiğinde, heap'in mevcut maksimumu sonuç olarak döndürülür.
Abartısız bir üst sınır yazmak için, durma koşulu sağlanmadan önce incelenen son parametreyi \(P\), bölen sayısı fonksiyonunu \(\tau(n)\), \(P\)'ye kadar saklanan asalların sayısını da \(\pi(P)\) ile gösterelim. Her \(p\le P\) için algoritma \(p^2+1\)'i mevcut asal tablosu üzerinden deneme bölmesiyle çarpanlara ayırır ve sonra ilgili bölenleri üretir. Yüksek seviyeli maliyet
$$T(P)=O\!\left(\sum_{p=1}^{P}\bigl(\pi(p)+\tau(p^2+1)\log k\bigr)\right)$$
şeklinde yazılabilir. Buradaki \(\pi(p)\) terimi yaklaşık \(\sqrt{p^2+1}\) düzeyine kadar yapılan asal denemelerini, \(\log k\) ise bir aday heap'e alındığında gerekebilecek güncellemeleri temsil eder.
Bellek kullanımı
$$O\bigl(k+\pi(P)+\max_{p\le P}\tau(p^2+1)\bigr)$$
ölçeğindedir. Baskın yapılar sabit boyutlu heap, aktif değerlerin hash set'i, büyüyen asal tablosu ve o anki çarpan ayrımına ait geçici bölen tamponudur. Yöntem etkilidir; çünkü üç değişkenli bir aramayı tek parametreli bir taramaya, bölen üretimine ve güçlü bir erken durdurma ölçütüne indirger.
Un entero Alexandrian es un entero positivo que proviene de un triple de enteros que satisface
$$\frac{1}{x}+\frac{1}{y}+\frac{1}{z}=\frac{1}{xyz}.$$
Para los valores positivos puede elegirse un triple generador con exactamente una entrada negativa, y el número que finalmente se ordena es \(A=\lvert xyz\rvert\). El Problema 221 pide el término número \(150000\) cuando todos esos enteros positivos se listan de menor a mayor.
La clave es que no hace falta buscar entre triples arbitrarios. La identidad de recíprocos se reduce a una condición muy rígida sobre divisores, de modo que cada entero Alexandrian válido nace de factorizar un número de la forma \(p^2+1\). Esa es la razón matemática por la que las implementaciones pueden evitar una búsqueda ingenua en tres variables.
La derivación usada por las implementaciones da una parametrización completa de todos los enteros Alexandrian que pueden aparecer en la secuencia ordenada.
Tomemos un triple válido en la forma \((-p,q,r)\) con \(p,q,r>0\). Al sustituirlo en la identidad definitoria se obtiene
$$-\frac{1}{p}+\frac{1}{q}+\frac{1}{r}=\frac{1}{(-p)qr}=-\frac{1}{pqr}.$$
Multiplicando por \(pqr\) desaparecen los denominadores y queda la ecuación diofántica
$$qr-pq-pr=1.$$
Así, una condición con recíprocos se convierte en una relación bilineal muy estructurada.
Sumemos \(p^2\) a ambos lados de la relación anterior:
$$qr-pq-pr+p^2=p^2+1.$$
El lado izquierdo factoriza de inmediato:
$$(q-p)(r-p)=p^2+1.$$
Definimos entonces
$$d=q-p,\qquad e=r-p.$$
Con eso, \(de=p^2+1\). Además, \(d\) y \(e\) tienen que ser positivos. Por ejemplo, si \(q\le p\), entonces \(qr-pq-pr\le pr-pq-pr=-pq\lt 0\), lo que contradice \(qr-pq-pr=1\). Por tanto, todo triple válido tiene la forma
$$(-p,\;p+d,\;p+e)\qquad\text{con}\qquad de=p^2+1.$$
El entero Alexandrian asociado es
$$A=\lvert (-p)(p+d)(p+e)\rvert=p(p+d)(p+e).$$
La recíproca es igual de importante: si \(p\ge 1\) y \(d,e\) son divisores positivos con \(de=p^2+1\), entonces \((-p,p+d,p+e)\) satisface la identidad original. No es solo una manera de fabricar ejemplos; es la clasificación completa que aprovecha el código.
Una vez fijado \(p\), la única libertad restante es el par de divisores \((d,e)\) de \(p^2+1\). Intercambiarlos no cambia el producto, porque
$$p(p+d)(p+e)=p(p+e)(p+d).$$
Por eso basta enumerar divisores \(d\le \sqrt{p^2+1}\) y recuperar el compañero \(e=(p^2+1)/d\). Así se elimina la duplicación trivial que proviene de los pares simétricos \((d,e)\) y \((e,d)\).
Si \(p=3\), entonces
$$p^2+1=10.$$
Los pares de divisores son \((1,10)\) y \((2,5)\). De ahí salen los triples
$$(-3,4,13)\qquad\text{y}\qquad(-3,5,8),$$
y por tanto los enteros Alexandrian
$$3\cdot 4\cdot 13=156,\qquad 3\cdot 5\cdot 8=120.$$
En efecto,
$$-\frac{1}{3}+\frac{1}{4}+\frac{1}{13}=-\frac{1}{156},\qquad -\frac{1}{3}+\frac{1}{5}+\frac{1}{8}=-\frac{1}{120}.$$
Este ejemplo aclara dos decisiones de implementación. Un mismo valor de \(p\) puede producir varios enteros Alexandrian, y esos valores no aparecen ya ordenados globalmente. Por eso el algoritmo va volcando candidatos en una estructura que conserva solo los más pequeños vistos hasta el momento.
Para cualquier parámetro futuro \(p'\) y cualquier par de divisores admisible, siempre se cumple \(d\ge 1\) y \(e\ge 1\). En consecuencia, todo candidato aún no visto satisface
$$A'=p'(p'+d)(p'+e)\ge p'(p'+1)^2.$$
Después de terminar todos los candidatos correspondientes a un cierto \(p\), para cualquier parámetro posterior \(p+1,p+2,\dots\) vale
$$A'\ge (p+1)(p+2)^2.$$
Si la estructura que guarda los \(k\) candidatos más pequeños ya está llena y esta cota inferior supera a su elemento máximo, entonces ningún valor futuro podrá entrar en ese conjunto de los \(k\) menores. En ese punto la búsqueda puede terminar, y el máximo actual es exactamente el \(k\)-ésimo entero Alexandrian.
Las implementaciones en C++, Python y Java recorren \(p=1,2,3,\dots\) en orden creciente. Para cada \(p\), forman \(n=p^2+1\), amplían una tabla incremental de números primos solo lo necesario para factorizar \(n\), y luego generan de manera recursiva todos los divisores \(d\le \sqrt{n}\). Cada uno de esos divisores determina el divisor complementario \(e=n/d\) y, con ello, un candidato \(A=p(p+d)(p+e)\).
En lugar de guardar todos los candidatos encontrados, las implementaciones mantienen un max-heap de tamaño fijo \(k\). Mientras ese heap no esté completo, se inserta cada nuevo candidato distinto. Una vez lleno, solo importan los candidatos menores que el máximo actual del heap; los valores mayores se descartan de inmediato. Un conjunto hash auxiliar registra los valores que están presentes en el heap para que un mismo entero Alexandrian no se cuente dos veces.
Las tres versiones difieren sobre todo en la representación numérica, no en la matemática. La implementación en C++ usa aritmética de 128 bits para los productos, la de Python utiliza enteros de precisión arbitraria y la de Java usa enteros grandes. Tras terminar cada valor de \(p\), aplican la cota inferior anterior. Cuando esa prueba demuestra que ningún \(p\) posterior puede mejorar el heap, el máximo actual del heap se devuelve como respuesta.
Sea \(P\) el último parámetro examinado antes de que se active el criterio de parada, sea \(\tau(n)\) la función que cuenta divisores y sea \(\pi(P)\) el número de primos almacenados hasta \(P\). Para cada \(p\le P\), el algoritmo factoriza \(p^2+1\) mediante división de prueba usando la tabla de primos ya construida y luego enumera los divisores relevantes. Una cota fiel a alto nivel es
$$T(P)=O\!\left(\sum_{p=1}^{P}\bigl(\pi(p)+\tau(p^2+1)\log k\bigr)\right).$$
El término \(\pi(p)\) refleja las pruebas con primos hasta aproximadamente \(\sqrt{p^2+1}\), y el factor \(\log k\) proviene de las posibles actualizaciones del heap cuando un candidato entra en el conjunto actual de los mejores \(k\).
El uso de memoria es
$$O\bigl(k+\pi(P)+\max_{p\le P}\tau(p^2+1)\bigr).$$
Los objetos dominantes son el heap acotado, el conjunto hash de valores activos, la tabla creciente de primos y un búfer temporal de divisores para la factorización en curso. El método es eficiente porque sustituye una búsqueda en tres variables por un recorrido en un solo parámetro, generación de divisores y una parada temprana muy fuerte.
Alexandrian 整数是由满足
$$\frac{1}{x}+\frac{1}{y}+\frac{1}{z}=\frac{1}{xyz}$$
的整数三元组产生的正整数。对于正的 Alexandrian 值,可以把生成三元组写成恰好只有一个负数的形式,此时最终排序的数就是 \(A=\lvert xyz\rvert\)。Problem 221 要求把所有这样的正整数按从小到大排列,并取第 \(150000\) 项。
关键不在于暴力搜索所有三元组,而在于上面的倒数恒等式会塌缩成一个非常刚性的因子分解条件。每一个合法的 Alexandrian 整数都来自某个 \(p^2+1\) 的因子对,这正是实现能够避开三变量穷举的根本原因。
三份实现都基于同一个完整参数化:把所有可能出现在有序序列中的 Alexandrian 整数都改写成一个单参数 \(p\) 加一个因子对 \((d,e)\) 的问题。
设一个合法三元组写成 \((-p,q,r)\),其中 \(p,q,r>0\)。代入定义式得到
$$-\frac{1}{p}+\frac{1}{q}+\frac{1}{r}=\frac{1}{(-p)qr}=-\frac{1}{pqr}.$$
两边同乘 \(pqr\),分母全部消失,得到
$$qr-pq-pr=1.$$
这样一来,原本看起来像分式恒等式的问题,变成了一个结构非常明确的丢番图方程。
在上式两边同时加上 \(p^2\):
$$qr-pq-pr+p^2=p^2+1.$$
左边可以立刻因式分解为
$$(q-p)(r-p)=p^2+1.$$
于是定义
$$d=q-p,\qquad e=r-p.$$
便有 \(de=p^2+1\)。而且 \(d,e\) 必须都是正数。原因很简单:如果 \(q\le p\),那么
$$qr-pq-pr\le pr-pq-pr=-pq\lt 0,$$
这与 \(qr-pq-pr=1\) 矛盾。于是每个合法三元组都只能写成
$$(-p,\;p+d,\;p+e)\qquad\text{其中}\qquad de=p^2+1.$$
对应的 Alexandrian 整数就是
$$A=\lvert (-p)(p+d)(p+e)\rvert=p(p+d)(p+e).$$
反过来也成立:只要 \(p\ge 1\),且 \(d,e\) 是满足 \(de=p^2+1\) 的正因子,那么 \((-p,p+d,p+e)\) 一定满足原始恒等式。这说明这里不是“找到一些例子”,而是得到了完整分类。
固定 \(p\) 以后,唯一需要选择的就是 \(p^2+1\) 的因子对 \((d,e)\)。交换 \(d\) 和 \(e\) 不会改变结果,因为
$$p(p+d)(p+e)=p(p+e)(p+d).$$
因此只需要枚举所有满足 \(d\le \sqrt{p^2+1}\) 的因子,再令 \(e=(p^2+1)/d\)。这样既不会漏解,也避免了 \((d,e)\) 与 \((e,d)\) 带来的镜像重复。
当 \(p=3\) 时,
$$p^2+1=10.$$
它的因子对是 \((1,10)\) 和 \((2,5)\)。于是得到两个三元组
$$(-3,4,13)\qquad\text{和}\qquad(-3,5,8),$$
对应的 Alexandrian 整数分别为
$$3\cdot 4\cdot 13=156,\qquad 3\cdot 5\cdot 8=120.$$
直接验证可知
$$-\frac{1}{3}+\frac{1}{4}+\frac{1}{13}=-\frac{1}{156},\qquad -\frac{1}{3}+\frac{1}{5}+\frac{1}{8}=-\frac{1}{120}.$$
这个例子说明了两个实现层面的事实。第一,同一个 \(p\) 可能对应多个 Alexandrian 整数。第二,这些数不会自动按全局升序出现,所以实现必须把候选值流式送入一个只保留当前最小若干项的数据结构。
对任意未来参数 \(p'\) 以及任意合法因子对,总有 \(d\ge 1\) 且 \(e\ge 1\)。因此任何尚未看到的候选值都满足
$$A'=p'(p'+d)(p'+e)\ge p'(p'+1)^2.$$
当某个 \(p\) 的所有候选都处理完之后,后续所有参数 \(p+1,p+2,\dots\) 统一满足
$$A'\ge (p+1)(p+2)^2.$$
如果此时保存当前最小 \(k\) 个候选值的容器已经装满,而且这个下界已经大于容器中的最大值,那么任何未来候选都不可能再进入这 \(k\) 个最小值之中。此时就可以安全停止搜索,容器中的最大值恰好就是第 \(k\) 个 Alexandrian 整数。
C++、Python 和 Java 三个实现都按 \(p=1,2,3,\dots\) 递增扫描。对每个 \(p\),先构造 \(n=p^2+1\),然后把增量维护的素数表扩展到足以分解 \(n\) 的范围,再递归生成所有满足 \(d\le \sqrt{n}\) 的因子。每个这样的 \(d\) 都对应补因子 \(e=n/d\),于是得到一个候选值 \(A=p(p+d)(p+e)\)。
实现并不会把所有候选值都永久保存下来,而是维护一个固定大小为 \(k\) 的大根堆。堆未满时,每个新的不同候选都加入进去;堆满之后,只有比当前堆顶更小的候选才有意义,更大的值立刻丢弃。与此同时,再配合一个哈希集合来记录当前堆中的数值,从而避免同一个 Alexandrian 整数被重复计入。
三种语言版本的差别主要在数值类型,而不在算法本身。C++ 用 128 位整数承载乘积,Python 使用任意精度整数,Java 使用大整数。每处理完一个 \(p\),实现都会检查前面推导出的下界。一旦下界证明后续参数不可能再改进当前堆,程序就返回堆顶,也就是所求结果。
设停止条件第一次成立前最后处理到的参数为 \(P\),记 \(\tau(n)\) 为约数个数函数,\(\pi(P)\) 为不超过 \(P\) 的已存素数个数。对于每个 \(p\le P\),算法都要用当前素数表对 \(p^2+1\) 做试除分解,然后枚举相关因子。因此一个贴近实现的高层复杂度界可以写成
$$T(P)=O\!\left(\sum_{p=1}^{P}\bigl(\pi(p)+\tau(p^2+1)\log k\bigr)\right).$$
其中 \(\pi(p)\) 反映了对大约 \(\sqrt{p^2+1}\) 范围内素数的试除,\(\log k\) 来自候选值进入当前最优 \(k\) 集合时可能触发的堆更新。
空间复杂度为
$$O\bigl(k+\pi(P)+\max_{p\le P}\tau(p^2+1)\bigr).$$
主要存储对象是固定大小的大根堆、活动候选的哈希集合、逐步扩展的素数表,以及当前一次分解过程中使用的临时因子缓冲区。这个方法之所以有效,是因为它把原本三变量的搜索压缩成了单参数扫描、因子生成和非常强的提前终止条件。
Александрийское число возникает из целочисленной тройки, удовлетворяющей равенству
$$\frac{1}{x}+\frac{1}{y}+\frac{1}{z}=\frac{1}{xyz}.$$
Для положительных значений можно выбрать порождающую тройку так, чтобы ровно один элемент был отрицательным; тогда упорядочиваемое число равно \(A=\lvert xyz\rvert\). В задаче 221 требуется найти \(150000\)-й член последовательности всех таких положительных чисел, отсортированных по возрастанию.
Суть решения в том, что перебирать произвольные тройки не нужно. Тождество с обратными величинами сводится к жесткому условию на делители, и каждое допустимое александрийское число возникает из разложения числа вида \(p^2+1\). Именно поэтому реализации обходятся без грубой силы по трем независимым переменным.
Во всех реализациях используется полная параметризация всех александрийских чисел, которые могут встретиться в упорядоченной последовательности.
Возьмем допустимую тройку в виде \((-p,q,r)\), где \(p,q,r>0\). Подстановка в определяющее равенство дает
$$-\frac{1}{p}+\frac{1}{q}+\frac{1}{r}=\frac{1}{(-p)qr}=-\frac{1}{pqr}.$$
После умножения на \(pqr\) знаменатели исчезают, и остается диофантово уравнение
$$qr-pq-pr=1.$$
То есть задача с тремя дробями превращается в очень жесткое билинейное условие на целые числа.
Прибавим \(p^2\) к обеим частям предыдущего равенства:
$$qr-pq-pr+p^2=p^2+1.$$
Левая часть сразу раскладывается:
$$(q-p)(r-p)=p^2+1.$$
Теперь введем
$$d=q-p,\qquad e=r-p.$$
Тогда \(de=p^2+1\). Кроме того, \(d\) и \(e\) обязаны быть положительными. Например, если \(q\le p\), то
$$qr-pq-pr\le pr-pq-pr=-pq\lt 0,$$
что противоречит равенству \(qr-pq-pr=1\). Следовательно, любая допустимая тройка имеет вид
$$(-p,\;p+d,\;p+e)\qquad\text{при}\qquad de=p^2+1.$$
Соответствующее александрийское число равно
$$A=\lvert (-p)(p+d)(p+e)\rvert=p(p+d)(p+e).$$
Обратное утверждение столь же важно: если \(p\ge 1\), а \(d,e\) являются положительными делителями с \(de=p^2+1\), то тройка \((-p,p+d,p+e)\) удовлетворяет исходному тождеству. Значит, это не просто удобная схема генерации примеров, а полная классификация, на которой построен код.
После фиксации \(p\) остается выбрать только пару делителей \((d,e)\) числа \(p^2+1\). Перестановка \(d\) и \(e\) не меняет итоговое произведение, потому что
$$p(p+d)(p+e)=p(p+e)(p+d).$$
Поэтому достаточно перечислять делители \(d\le \sqrt{p^2+1}\), а второй делитель восстанавливать как \(e=(p^2+1)/d\). Это убирает тривиальные зеркальные дубликаты \((d,e)\) и \((e,d)\).
При \(p=3\) имеем
$$p^2+1=10.$$
Пары делителей здесь \((1,10)\) и \((2,5)\). Они дают тройки
$$(-3,4,13)\qquad\text{и}\qquad(-3,5,8),$$
а значит, александрийские числа
$$3\cdot 4\cdot 13=156,\qquad 3\cdot 5\cdot 8=120.$$
Проверка прямой подстановкой дает
$$-\frac{1}{3}+\frac{1}{4}+\frac{1}{13}=-\frac{1}{156},\qquad -\frac{1}{3}+\frac{1}{5}+\frac{1}{8}=-\frac{1}{120}.$$
Этот пример объясняет два важных инженерных решения. Во-первых, одно и то же значение \(p\) может породить несколько александрийских чисел. Во-вторых, они не появляются сразу в общем отсортированном порядке. Поэтому реализации направляют кандидаты в структуру, которая хранит только наименьшие значения, найденные к текущему моменту.
Для любого будущего параметра \(p'\) и любой допустимой пары делителей всегда выполняется \(d\ge 1\) и \(e\ge 1\). Следовательно, каждый еще не просмотренный кандидат удовлетворяет неравенству
$$A'=p'(p'+d)(p'+e)\ge p'(p'+1)^2.$$
После завершения обработки некоторого значения \(p\) для всех следующих параметров \(p+1,p+2,\dots\) верно
$$A'\ge (p+1)(p+2)^2.$$
Если контейнер с текущими \(k\) наименьшими кандидатами уже заполнен и эта нижняя граница больше его максимального элемента, то ни одно будущее значение не сможет войти в набор из \(k\) наименьших. В этот момент поиск можно закончить, а текущий максимум контейнера и есть искомое \(k\)-е александрийское число.
Реализации на C++, Python и Java перебирают \(p=1,2,3,\dots\) по возрастанию. Для каждого \(p\) строится \(n=p^2+1\), затем инкрементальная таблица простых чисел расширяется ровно настолько, чтобы можно было разложить \(n\), после чего рекурсивно перечисляются все делители \(d\le \sqrt{n}\). Каждый такой делитель определяет дополнительный делитель \(e=n/d\) и тем самым одного кандидата \(A=p(p+d)(p+e)\).
Вместо хранения всех когда-либо встреченных кандидатов поддерживается max-heap фиксированного размера \(k\). Пока он не заполнен, каждый новый уникальный кандидат просто добавляется. После заполнения имеют значение только те кандидаты, которые меньше текущего максимума в куче; более крупные значения сразу отбрасываются. Дополнительное hash-множество отслеживает числа, которые сейчас лежат в куче, чтобы одно и то же александрийское число не учитывалось дважды.
Различия между тремя версиями касаются главным образом числовых типов, а не математики. В C++ для произведений используется 128-битная арифметика, в Python доступны целые произвольной длины, а в Java применяются большие целые числа. После каждого обработанного значения \(p\) выполняется проверка нижней границы. Как только она доказывает, что ни один больший параметр уже не сможет улучшить кучу, текущий максимум в куче возвращается как ответ.
Обозначим через \(P\) последний параметр, обработанный до срабатывания критерия остановки, через \(\tau(n)\) функцию числа делителей, а через \(\pi(P)\) число хранимых простых чисел не больше \(P\). Для каждого \(p\le P\) алгоритм раскладывает \(p^2+1\) пробным делением по текущей таблице простых, а затем перечисляет нужные делители. Достаточно точная верхняя оценка имеет вид
$$T(P)=O\!\left(\sum_{p=1}^{P}\bigl(\pi(p)+\tau(p^2+1)\log k\bigr)\right).$$
Слагаемое \(\pi(p)\) отражает проверку простых примерно до \(\sqrt{p^2+1}\), а множитель \(\log k\) появляется из возможных операций с кучей, когда кандидат попадает в текущую лучшую \(k\)-ку.
Память оценивается как
$$O\bigl(k+\pi(P)+\max_{p\le P}\tau(p^2+1)\bigr).$$
Основные хранимые структуры здесь: ограниченная куча, hash-множество активных значений, растущая таблица простых чисел и временный буфер делителей для текущего разложения. Метод эффективен потому, что сводит поиск по трем переменным к проходу по одному параметру, генерации делителей и сильному условию ранней остановки.
العدد الألكسندري هو عدد صحيح موجب ينتج من ثلاثية صحيحة تحقق العلاقة
$$\frac{1}{x}+\frac{1}{y}+\frac{1}{z}=\frac{1}{xyz}.$$
وللأعداد الألكسندرية الموجبة يمكن اختيار الثلاثية المولدة بحيث تحتوي على حد سالب واحد فقط، وعندها يكون العدد المرتب في المتتالية هو \(A=\lvert xyz\rvert\). مسألة 221 تطلب إيجاد الحد رقم \(150000\) بعد ترتيب جميع هذه الأعداد الموجبة تصاعديًا.
الفكرة الأساسية هي أن البحث ليس على جميع الثلاثيات الممكنة. فهذه المتطابقة الخاصة بالمقلوبات تنكمش إلى شرط صارم جدًا على القواسم، بحيث إن كل عدد ألكسندري صحيح صالح يأتي من تحليل عدد على الصورة \(p^2+1\). لهذا تستطيع التطبيقات تجنب البحث الخام في ثلاثة متغيرات مستقلة.
الاشتقاق المستخدم في التطبيقات يعطي توصيفًا كاملًا لكل الأعداد الألكسندرية التي يمكن أن تظهر في الترتيب النهائي.
لنأخذ ثلاثية صالحة على الصورة \((-p,q,r)\) حيث \(p,q,r>0\). عند التعويض في العلاقة التعريفية نحصل على
$$-\frac{1}{p}+\frac{1}{q}+\frac{1}{r}=\frac{1}{(-p)qr}=-\frac{1}{pqr}.$$
وبضرب الطرفين في \(pqr\) تختفي المقامات، فنصل إلى المعادلة الديوفانتية
$$qr-pq-pr=1.$$
أي إن مسألة تبدو في البداية كجمع مقلوبات تتحول إلى علاقة خطية-ضربية شديدة التقييد بين الأعداد الصحيحة.
إذا أضفنا \(p^2\) إلى طرفي المعادلة السابقة فسنحصل على
$$qr-pq-pr+p^2=p^2+1.$$
والطرف الأيسر يتحلل مباشرة إلى
$$(q-p)(r-p)=p^2+1.$$
لذلك نعرّف
$$d=q-p,\qquad e=r-p.$$
فنحصل على \(de=p^2+1\). كما أن \(d\) و\(e\) لا بد أن يكونا موجبين. فمثلًا إذا كان \(q\le p\) فإن
$$qr-pq-pr\le pr-pq-pr=-pq\lt 0,$$
وهذا يناقض الشرط \(qr-pq-pr=1\). إذن كل ثلاثية صالحة لا بد أن تكون على الصورة
$$(-p,\;p+d,\;p+e),\qquad de=p^2+1.$$
والعدد الألكسندري الموافق لها هو
$$A=\lvert (-p)(p+d)(p+e)\rvert=p(p+d)(p+e).$$
والاتجاه العكسي مهم بالقدر نفسه: إذا اخترنا \(p\ge 1\) وقاسمين موجبين \(d,e\) يحققان \(de=p^2+1\)، فإن الثلاثية \((-p,p+d,p+e)\) تحقق المتطابقة الأصلية. لذلك فهذه ليست مجرد طريقة لبناء أمثلة، بل هي الوصف الكامل الذي تعتمد عليه الشيفرات.
بعد تثبيت \(p\) لا يبقى إلا اختيار زوج القواسم \((d,e)\) للعدد \(p^2+1\). تبديل \(d\) و\(e\) لا يغيّر القيمة الناتجة لأن
$$p(p+d)(p+e)=p(p+e)(p+d).$$
لهذا يكفي تعداد كل قاسم \(d\le \sqrt{p^2+1}\)، ثم استنتاج القاسم المتمم \(e=(p^2+1)/d\). بهذه الطريقة نتجنب التكرار المرآتي البسيط الناتج من الزوجين \((d,e)\) و\((e,d)\).
عندما يكون \(p=3\) نحصل على
$$p^2+1=10.$$
وأزواج القواسم هي \((1,10)\) و\((2,5)\). لذلك نحصل على الثلاثيتين
$$(-3,4,13),\qquad(-3,5,8).$$
ومن ثم يكون العددان الألكسندريان
$$3\cdot 4\cdot 13=156,\qquad 3\cdot 5\cdot 8=120.$$
وبالفعل
$$-\frac{1}{3}+\frac{1}{4}+\frac{1}{13}=-\frac{1}{156},\qquad -\frac{1}{3}+\frac{1}{5}+\frac{1}{8}=-\frac{1}{120}.$$
هذا المثال يوضح قرارين مهمين في التنفيذ. القيمة الواحدة لـ \(p\) قد تولد أكثر من عدد ألكسندري واحد، وهذه القيم لا تصل أصلًا بترتيب عالمي تصاعدي. لذلك تُمرَّر المرشحات إلى بنية بيانات تحتفظ فقط بأصغر القيم التي ظهرت حتى تلك اللحظة.
لكل معامل مستقبلي \(p'\) ولكل زوج قواسم صالح، لدينا دائمًا \(d\ge 1\) و\(e\ge 1\). لذلك فإن أي مرشح لم يُر بعد يحقق
$$A'=p'(p'+d)(p'+e)\ge p'(p'+1)^2.$$
وبعد الانتهاء من جميع المرشحات الخاصة بقيمة معينة من \(p\)، فإن كل قيمة لاحقة \(p+1,p+2,\dots\) تحقق
$$A'\ge (p+1)(p+2)^2.$$
إذا كانت البنية التي تحفظ أصغر \(k\) مرشحات قد امتلأت بالفعل، وكان هذا الحد الأدنى أكبر من أكبر عنصر فيها، فمعنى ذلك أن أي قيمة مستقبلية لن تتمكن من دخول مجموعة أصغر \(k\) أعداد. عند تلك النقطة يمكن إيقاف البحث بأمان، ويكون العنصر الأكبر الحالي هو بالضبط العدد الألكسندري رقم \(k\).
تنطلق تطبيقات C++ وPython وJava بتمرير \(p=1,2,3,\dots\) تصاعديًا. ولكل \(p\) تُنشأ القيمة \(n=p^2+1\)، ثم تُوسَّع قائمة أولية متزايدة بالقدر الكافي لتحليل \(n\) إلى عوامله، وبعد ذلك تُولَّد كل القواسم \(d\le \sqrt{n}\) بطريقة عودية. وكل قاسم من هذا النوع يحدد القاسم المكمل \(e=n/d\)، ومن ثم مرشحًا واحدًا هو \(A=p(p+d)(p+e)\).
بدل الاحتفاظ بكل المرشحات التي تظهر أثناء التنفيذ، تحافظ التطبيقات على كومة عظمى ذات حجم ثابت \(k\). ما دامت الكومة غير ممتلئة، يضاف إليها كل مرشح جديد ومميز. وبعد الامتلاء، لا تعود مهمة إلا المرشحات الأصغر من أكبر عنصر حالي في الكومة؛ أما القيم الأكبر فتُرفض فورًا. كما تُستخدم مجموعة hash مرافقة لتتبع القيم الموجودة حاليًا داخل الكومة حتى لا يُحسب العدد الألكسندري نفسه مرتين.
الاختلاف بين اللغات الثلاث هو في تمثيل الأعداد أكثر منه في الفكرة الرياضية. فنسخة C++ تستخدم حسابًا على 128 بت للجداءات، ونسخة Python تستفيد من الأعداد الصحيحة غير المحدودة عمليًا، أما نسخة Java فتستخدم أعدادًا صحيحة كبيرة. وبعد الانتهاء من كل قيمة \(p\)، يُفحص الحد الأدنى المذكور سابقًا. وما إن يثبت هذا الفحص أن أي \(p\) لاحق لن يحسن محتوى الكومة، حتى يُعاد أكبر عنصر فيها بوصفه الجواب.
لنرمز بـ \(P\) إلى آخر معامل فُحص قبل نجاح شرط الإيقاف، وبـ \(\tau(n)\) إلى دالة عدد القواسم، وبـ \(\pi(P)\) إلى عدد الأعداد الأولية المخزنة حتى \(P\). لكل \(p\le P\)، يقوم الخوارزم بتحليل \(p^2+1\) بالقسمة التجريبية على الأعداد الأولية المحفوظة، ثم يولّد القواسم المهمة. ويمكن كتابة حد علوي معبر على المستوى العالي بالشكل
$$T(P)=O\!\left(\sum_{p=1}^{P}\bigl(\pi(p)+\tau(p^2+1)\log k\bigr)\right).$$
الحد \(\pi(p)\) يعكس اختبار الأعداد الأولية حتى حدود \(\sqrt{p^2+1}\) تقريبًا، في حين يأتي العامل \(\log k\) من عمليات تحديث الكومة عندما يُقبل مرشح ضمن أفضل \(k\) قيم حالية.
أما الذاكرة فتقاس بـ
$$O\bigl(k+\pi(P)+\max_{p\le P}\tau(p^2+1)\bigr).$$
وأهم البنى المخزنة هي الكومة محدودة الحجم، ومجموعة القيم النشطة، وجدول الأعداد الأولية المتنامي، ومخزن مؤقت للقواسم الخاصة بالتحليل الحالي. وتنبع كفاءة هذه الطريقة من أنها تستبدل بحثًا ثلاثي المتغيرات بمسح أحادي المعامل مع توليد قواسم وشرط إيقاف مبكر قوي.