Problem Summary

Let \(f(n)\) be the number of positive-integer solutions of

$$\frac{1}{a}+\frac{1}{b}=\frac{p}{10^n}.$$

The Project Euler task is to compute \(\sum_{n=1}^{9} f(n)\). The variable \(p\) is part of the solution rather than an input, so the real difficulty is to understand which pairs \((a,b)\) can occur and how many values of \(p\) they generate.

A direct search is not realistic because \(a\) and \(b\) are not bounded in advance. The key simplification is to separate the common factor of \(a\) and \(b\), reduce the problem to a coprime core, and then count all lifts of that core through the divisor function.

Mathematical Approach

The entire solution turns on one observation: once the common factor of \(a\) and \(b\) is removed, the remaining coprime pieces can only involve the primes 2 and 5, because the right-hand side has denominator \(10^n=2^n5^n\).

Strip off the gcd

Write

$$a=dx,\qquad b=dy,\qquad \gcd(x,y)=1.$$

Substituting into the equation gives

$$\frac{1}{dx}+\frac{1}{dy}=\frac{x+y}{dxy}=\frac{p}{10^n},$$

so after clearing denominators we get

$$10^n(x+y)=pdxy.$$

For a fixed coprime pair \((x,y)\), all remaining freedom is carried by the common factor \(d\) and the numerator \(p\).

Why the reduced denominators must divide \(10^n\)

If a prime divides both \(xy\) and \(x+y\), then it divides one of \(x\) or \(y\), and therefore also the other, contradicting \(\gcd(x,y)=1\). Hence

$$\gcd(xy,x+y)=1.$$

From

$$10^n(x+y)=pdxy$$

it follows that every prime factor of \(xy\) must already come from \(10^n\). Therefore

$$xy\mid 10^n,$$

so \(x\) and \(y\) can only use the primes 2 and 5. We may write

$$x=2^u5^v,\qquad y=2^r5^s,$$

with

$$u+r\le n,\qquad v+s\le n,\qquad \min(u,r)=0,\qquad \min(v,s)=0.$$

The last two conditions express the coprimality of \(x\) and \(y\): for each prime, all of its exponent sits on one side or the other, never both.

Canonical reduced pairs

The equation is symmetric in \(a\) and \(b\), so after reducing to \((x,y)\) we only need one canonical ordering for the coprime pair. Because only the primes 2 and 5 are available, every reduced pair falls into one of two families:

$$\bigl(1,2^\alpha5^\beta\bigr)\quad\text{with}\quad 0\le \alpha,\beta\le n,$$

or

$$\bigl(2^\alpha,5^\beta\bigr)\quad\text{with}\quad 1\le \alpha,\beta\le n.$$

The first family covers the case where one reduced denominator receives both prime powers, and the second family covers the split case where one side is a pure power of 2 and the other is a pure power of 5. This is exactly the symmetry reduction encoded by the implementations.

Each reduced pair contributes a divisor count

Rearrange the main equation as

$$pd=\frac{10^n(x+y)}{xy}=(x+y)2^{\,n-u-r}5^{\,n-v-s}=:K.$$

Now fix a valid coprime pair \((x,y)\). If \(d\) is any positive divisor of \(K\), then

$$a=dx,\qquad b=dy,\qquad p=\frac{K}{d}$$

gives a positive-integer solution. Conversely, every solution with this reduced pair must satisfy \(d\mid K\). So the number of solutions arising from one canonical pair \((x,y)\) is exactly

$$\tau(K),$$

where \(\tau\) is the divisor-counting function. The whole problem is therefore reduced to enumerating the canonical coprime pairs and summing \(\tau(K)\).

Worked Example: \(n=1\)

For \(n=1\), the canonical reduced pairs are

$$ (1,1),\ (1,2),\ (1,5),\ (1,10),\ (2,5). $$

The corresponding values of \(K\) are

$$ 20,\ 15,\ 12,\ 11,\ 7, $$

so their contributions are

$$ \tau(20)=6,\quad \tau(15)=4,\quad \tau(12)=6,\quad \tau(11)=2,\quad \tau(7)=2. $$

Adding them gives

$$f(1)=6+4+6+2+2=20,$$

which matches the published checkpoint. The divisor interpretation is concrete here: for the reduced pair \((x,y)=(1,1)\), we have \(K=20\), and every divisor \(d\) of 20 produces a solution \((a,b,p)=(d,d,20/d)\).

How the Code Works

The C++, Python, and Java implementations never search over \(a\), \(b\), or \(p\) directly. They iterate over the exponents of 2 and 5 that define the canonical reduced pair, compute the corresponding value of \(K\), and add its number of divisors.

Enumerating the canonical exponent patterns

One exponent of 2 is pinned to zero from the start, which forces a unique orientation whenever one reduced denominator carries a factor of 2. If neither side carries a factor of 2, one exponent of 5 is also pinned to zero, removing the remaining swap symmetry. In effect, this loop structure enumerates exactly the two mathematical families \(\bigl(1,2^\alpha5^\beta\bigr)\) and \(\bigl(2^\alpha,5^\beta\bigr)\) without duplicates.

Turning one candidate into a contribution

For each exponent tuple, the implementation reconstructs the two reduced denominators, forms the scaling factor \(2^{n-u-r}5^{n-v-s}\), and evaluates

$$K=(x+y)2^{\,n-u-r}5^{\,n-v-s}.$$

It then factors \(K\) by trial division and converts the prime exponents into \(\tau(K)\). That value is added to the running total for the current \(n\), and the outer loop sums the counts for \(n=1\) through \(9\). The C++ and Python implementations also verify the published checkpoint \(f(1)=20\) before printing the final total.

Complexity Analysis

For a fixed \(n\), the canonical pairs are easy to count: there are \((n+1)^2\) pairs of the form \(\bigl(1,2^\alpha5^\beta\bigr)\) and \(n^2\) pairs of the form \(\bigl(2^\alpha,5^\beta\bigr)\). So the enumeration cost is \(O(n^2)\) candidates per \(n\).

For each candidate, the implementations factor \(K\) by trial division, which costs \(O(\sqrt{K})\) in the worst case. In this problem \(K\) is at most on the order of \(10^n\), and the Euler target only needs \(n\le 9\), so the numeric work is tiny in practice. Memory usage is \(O(1)\), because only a handful of integers are stored at any moment.

Footnotes and References

  1. Problem page: https://projecteuler.net/problem=157
  2. Diophantine equation: Wikipedia - Diophantine equation
  3. Divisor function: Wikipedia - Divisor function
  4. Greatest common divisor: Wikipedia - Greatest common divisor
  5. Fundamental theorem of arithmetic: Wikipedia - Fundamental theorem of arithmetic

Problemzusammenfassung

Sei \(f(n)\) die Anzahl der positiven ganzzahligen Lösungen von

$$\frac{1}{a}+\frac{1}{b}=\frac{p}{10^n}.$$

Gesucht ist in Project Euler der Wert

$$\sum_{n=1}^{9} f(n).$$

Dabei ist \(p\) keine feste Eingabe, sondern Teil der Lösung. Man muss also nicht nur passende Nenner \(a\) und \(b\) finden, sondern gleichzeitig verstehen, wie viele zugehörige Werte von \(p\) daraus entstehen.

Ein direkter Suchansatz ist unbrauchbar, weil \(a\) und \(b\) nicht vorab beschränkt sind. Die Lösung funktioniert nur deshalb schnell, weil man zuerst den gemeinsamen Faktor von \(a\) und \(b\) abspaltet, dann nur noch ein teilerfremdes Kernpaar betrachtet und schließlich dessen Hebungen über die Teilerfunktion zählt.

Mathematischer Ansatz

Der Kern der Aufgabe ist überraschend starr: Nach dem Herausziehen des größten gemeinsamen Teilers können in den reduzierten Nennern nur noch die Primzahlen 2 und 5 vorkommen, denn die rechte Seite besitzt den Nenner \(10^n=2^n5^n\).

Den ggT herausziehen

Schreibe

$$a=dx,\qquad b=dy,\qquad \gcd(x,y)=1.$$

Einsetzen liefert

$$\frac{1}{dx}+\frac{1}{dy}=\frac{x+y}{dxy}=\frac{p}{10^n},$$

also nach Multiplikation mit allen Nennern

$$10^n(x+y)=pdxy.$$

Für ein festes teilerfremdes Paar \((x,y)\) liegt die gesamte Restfreiheit nun in \(d\) und \(p\).

Warum die reduzierten Nenner Teiler von \(10^n\) sein müssen

Teilt eine Primzahl sowohl \(xy\) als auch \(x+y\), dann teilt sie wegen \(xy\) entweder \(x\) oder \(y\) und damit aus \(x+y\) auch den jeweils anderen Summanden. Das widerspricht \(\gcd(x,y)=1\). Also gilt

$$\gcd(xy,x+y)=1.$$

Aus

$$10^n(x+y)=pdxy$$

folgt daher, dass alle Primfaktoren von \(xy\) bereits in \(10^n\) enthalten sein müssen. Somit

$$xy\mid 10^n,$$

und daher haben \(x\) und \(y\) nur die Primfaktoren 2 und 5. Man kann also schreiben

$$x=2^u5^v,\qquad y=2^r5^s,$$

mit

$$u+r\le n,\qquad v+s\le n,\qquad \min(u,r)=0,\qquad \min(v,s)=0.$$

Die letzten beiden Bedingungen kodieren die Teilerfremdheit: Für jede der beiden Primzahlen liegt die gesamte Potenz entweder ganz links oder ganz rechts.

Kanonische reduzierte Paare

Die Gleichung ist symmetrisch in \(a\) und \(b\). Deshalb genügt es, für das reduzierte Paar \((x,y)\) nur eine kanonische Reihenfolge zu zählen. Da nur die Primzahlen 2 und 5 vorkommen dürfen, bleibt bis auf Vertauschung genau zwei Typen übrig:

$$\bigl(1,2^\alpha5^\beta\bigr)\quad\text{mit}\quad 0\le \alpha,\beta\le n,$$

oder

$$\bigl(2^\alpha,5^\beta\bigr)\quad\text{mit}\quad 1\le \alpha,\beta\le n.$$

Der erste Typ beschreibt den Fall, dass eine Seite sowohl die Zweier- als auch die Fünferpotenz trägt. Der zweite Typ beschreibt die echte Aufteilung, bei der eine Seite nur eine Zweierpotenz und die andere nur eine Fünferpotenz besitzt. Genau diese Fallunterscheidung steckt in den Schleifen der Implementierungen.

Jedes reduzierte Paar liefert eine Teileranzahl

Die Hauptgleichung lässt sich umformen zu

$$pd=\frac{10^n(x+y)}{xy}=(x+y)2^{\,n-u-r}5^{\,n-v-s}=:K.$$

Fixiere nun ein gültiges reduziertes Paar \((x,y)\). Für jeden positiven Teiler \(d\) von \(K\) erhält man durch

$$a=dx,\qquad b=dy,\qquad p=\frac{K}{d}$$

eine Lösung in positiven ganzen Zahlen. Umgekehrt muss jede Lösung mit genau diesem reduzierten Paar einen Teiler \(d\mid K\) verwenden. Also ist die Anzahl der zugehörigen Lösungen exakt

$$\tau(K),$$

wobei \(\tau\) die Anzahl der positiven Teiler bezeichnet. Damit reduziert sich die gesamte Aufgabe auf das Auflisten aller kanonischen reduzierten Paare und das Summieren von \(\tau(K)\).

Durchgerechnetes Beispiel: \(n=1\)

Für \(n=1\) gibt es genau die kanonischen reduzierten Paare

$$ (1,1),\ (1,2),\ (1,5),\ (1,10),\ (2,5). $$

Daraus entstehen die Werte

$$ 20,\ 15,\ 12,\ 11,\ 7 $$

für \(K\), also die Beiträge

$$ \tau(20)=6,\quad \tau(15)=4,\quad \tau(12)=6,\quad \tau(11)=2,\quad \tau(7)=2. $$

Somit

$$f(1)=6+4+6+2+2=20,$$

genau wie im veröffentlichten Kontrollwert. Besonders anschaulich ist das Paar \((x,y)=(1,1)\): Hier ist \(K=20\), und jeder Teiler \(d\) von 20 erzeugt unmittelbar die Lösung \((a,b,p)=(d,d,20/d)\).

Wie der Code arbeitet

Die C++-, Python- und Java-Implementierungen durchsuchen niemals direkt die Werte von \(a\), \(b\) oder \(p\). Stattdessen laufen sie über die Exponenten von 2 und 5, die das kanonische reduzierte Paar bestimmen, berechnen daraus \(K\) und addieren dessen Teileranzahl.

Die kanonischen Exponentenmuster erzeugen

Eine Zweierpotenz wird von Anfang an auf Exponent 0 festgelegt. Dadurch ist die Orientierung eindeutig, sobald eine reduzierte Seite überhaupt einen Faktor 2 trägt. Falls keine Seite einen Faktor 2 hat, wird zusätzlich eine Fünferpotenz auf Exponent 0 fixiert, damit auch dort die Vertauschungssymmetrie verschwindet. Genau dadurch entstehen ohne Doppelzählung die beiden mathematischen Familien \(\bigl(1,2^\alpha5^\beta\bigr)\) und \(\bigl(2^\alpha,5^\beta\bigr)\).

Einen Kandidaten in einen Beitrag umwandeln

Zu jedem Exponententupel rekonstruiert die Implementierung die beiden reduzierten Nenner, bildet den Skalenfaktor \(2^{n-u-r}5^{n-v-s}\) und berechnet

$$K=(x+y)2^{\,n-u-r}5^{\,n-v-s}.$$

Anschließend wird \(K\) per Probedivision faktorisiert, und aus den Exponenten der Primfaktoren wird \(\tau(K)\) bestimmt. Dieser Wert fließt in die Summe für das aktuelle \(n\) ein; die äußere Schleife akkumuliert anschließend über \(n=1\) bis \(9\). Die C++- und Python-Version prüfen außerdem den bekannten Kontrollwert \(f(1)=20\), bevor sie das Endergebnis ausgeben.

Komplexitätsanalyse

Für festes \(n\) ist die Anzahl der Kandidaten klein und exakt bekannt: \((n+1)^2\) Paare vom Typ \(\bigl(1,2^\alpha5^\beta\bigr)\) und \(n^2\) Paare vom Typ \(\bigl(2^\alpha,5^\beta\bigr)\). Die Enumeration kostet also \(O(n^2)\) Kandidaten pro \(n\).

Jeder Kandidat benötigt anschließend eine Probedivision von \(K\), also im Worst Case \(O(\sqrt{K})\). In dieser Aufgabe ist \(K\) jedoch nur von Größenordnung \(10^n\), und benötigt werden ausschließlich \(n\le 9\). Deshalb ist die Laufzeit praktisch sehr klein. Der Speicherverbrauch ist \(O(1)\), da nur wenige Ganzzahlen gleichzeitig gehalten werden.

Fußnoten und Referenzen

  1. Problemseite: https://projecteuler.net/problem=157
  2. Diophantische Gleichung: Wikipedia - Diophantine equation
  3. Teilerfunktion: Wikipedia - Divisor function
  4. Größter gemeinsamer Teiler: Wikipedia - Greatest common divisor
  5. Hauptsatz der Arithmetik: Wikipedia - Fundamental theorem of arithmetic

Problem Özeti

\(f(n)\),

$$\frac{1}{a}+\frac{1}{b}=\frac{p}{10^n}$$

denklemini sağlayan pozitif tamsayı çözümlerinin sayısı olsun. Project Euler görevi

$$\sum_{n=1}^{9} f(n)$$

değerini hesaplamaktır. Burada \(p\) sabit verilmez; çözümün bir parçası olarak ortaya çıkar. Bu yüzden asıl mesele, hangi \((a,b)\) çiftlerinin mümkün olduğunu ve her böyle çiftin kaç farklı \(p\) ürettiğini anlamaktır.

Doğrudan arama pratik değildir, çünkü \(a\) ve \(b\) için önceden verilmiş bir üst sınır yoktur. Hızlı çözüm, önce \(a\) ile \(b\)'nin ortak çarpanını ayırır, sonra geriye kalan aralarında asal çekirdeği inceler ve son olarak bu çekirdeğin kaç farklı şekilde genişletilebildiğini bölen sayısı fonksiyonuyla sayar.

Matematiksel Yaklaşım

Tüm çözüm şu olguya dayanır: \(a\) ile \(b\)'nin ortak kısmını çıkardıktan sonra geriye kalan indirgenmiş paydalar yalnızca 2 ve 5 asalını içerebilir; çünkü sağ taraftaki payda \(10^n=2^n5^n\) biçimindedir.

EBOB'u ayırmak

Şöyle yazalım:

$$a=dx,\qquad b=dy,\qquad \gcd(x,y)=1.$$

Denkleme yerleştirince

$$\frac{1}{dx}+\frac{1}{dy}=\frac{x+y}{dxy}=\frac{p}{10^n}$$

elde edilir; paydaları temizlersek

$$10^n(x+y)=pdxy$$

olur. Yani sabit bir aralarında asal \((x,y)\) çifti için geriye kalan serbestlik yalnızca \(d\) ve \(p\) üzerindedir.

İndirgenmiş paydalar neden \(10^n\)'yi bölmek zorunda?

Bir asal sayı hem \(xy\)'yi hem de \(x+y\)'yi bölüyorsa, \(xy\)'yi böldüğü için \(x\) ya da \(y\)'den birini böler; ardından \(x+y\)'yi de böldüğü için öteki terimi de bölmek zorunda kalır. Bu, \(\gcd(x,y)=1\) ile çelişir. Dolayısıyla

$$\gcd(xy,x+y)=1.$$

Şimdi

$$10^n(x+y)=pdxy$$

eşitliğine bakınca, \(xy\)'nin her asal çarpanının zaten \(10^n\)'den gelmesi gerektiği görülür. O halde

$$xy\mid 10^n,$$

ve bu da \(x\) ile \(y\)'nin yalnızca 2 ve 5 kuvvetlerinden oluştuğu anlamına gelir:

$$x=2^u5^v,\qquad y=2^r5^s,$$

burada

$$u+r\le n,\qquad v+s\le n,\qquad \min(u,r)=0,\qquad \min(v,s)=0.$$

Son iki koşul, aralarında asallığın tam ifadesidir: her asalın tüm kuvveti ya solda ya sağdadır, iki tarafa birden dağılmaz.

Kanonik indirgenmiş çiftler

Denklem \(a\) ile \(b\) arasında simetriktir. Bu yüzden \((x,y)\) için yalnızca tek bir kanonik sıralama saymak yeterlidir. Kullanılabilecek asallar sadece 2 ve 5 olduğundan, her indirgenmiş çift iki aileden birine düşer:

$$\bigl(1,2^\alpha5^\beta\bigr)\quad\text{ve}\quad 0\le \alpha,\beta\le n,$$

veya

$$\bigl(2^\alpha,5^\beta\bigr)\quad\text{ve}\quad 1\le \alpha,\beta\le n.$$

İlk ailede indirgenmiş paydalardan biri hem 2 hem 5 kuvvetini taşır, öteki taraf 1 olur. İkinci ailede ise 2 kuvveti ile 5 kuvveti iki tarafa ayrılır. Uygulamaların yaptığı simetri kırma tam olarak bu iki aileyi tekrar üretmeden dolaşmaktır.

Her indirgenmiş çift bir bölen sayısı kadar katkı yapar

Ana eşitliği şu biçimde yazabiliriz:

$$pd=\frac{10^n(x+y)}{xy}=(x+y)2^{\,n-u-r}5^{\,n-v-s}=:K.$$

Şimdi geçerli bir \((x,y)\) indirgenmiş çiftini sabitleyelim. \(K\)'nin her pozitif böleni \(d\) için

$$a=dx,\qquad b=dy,\qquad p=\frac{K}{d}$$

pozitif tamsayı çözümü verir. Tersi de doğrudur: bu indirgenmiş çiftten gelen her çözüm mutlaka \(d\mid K\) koşulunu sağlar. Dolayısıyla tek bir kanonik \((x,y)\) çiftinin katkısı tam olarak

$$\tau(K)$$

kadardır. Buradaki \(\tau\), pozitif bölen sayısı fonksiyonudur. Böylece tüm problem, kanonik indirgenmiş çiftleri sıralayıp bunlara karşılık gelen \(\tau(K)\) değerlerini toplamaya indirgenir.

Çalışılmış Örnek: \(n=1\)

\(n=1\) için kanonik indirgenmiş çiftler

$$ (1,1),\ (1,2),\ (1,5),\ (1,10),\ (2,5) $$

olur. Bunların ürettiği \(K\) değerleri

$$ 20,\ 15,\ 12,\ 11,\ 7 $$

ve katkıları da

$$ \tau(20)=6,\quad \tau(15)=4,\quad \tau(12)=6,\quad \tau(11)=2,\quad \tau(7)=2 $$

şeklindedir. Toplam

$$f(1)=6+4+6+2+2=20$$

çıkar ve bu yayımlanan kontrol değeriyle aynıdır. Özellikle \((x,y)=(1,1)\) için \(K=20\) olduğundan, 20'nin her böleni \(d\) doğrudan \((a,b,p)=(d,d,20/d)\) çözümünü verir.

Kod Nasıl Çalışır

C++, Python ve Java uygulamaları \(a\), \(b\) veya \(p\) üzerinde doğrudan arama yapmaz. Bunun yerine, kanonik indirgenmiş çifti tanımlayan 2 ve 5 üsleri üzerinde dolaşır, ilgili \(K\) değerini hesaplar ve onun bölen sayısını toplar.

Kanonik üs örüntülerini üretmek

2'nin üslerinden biri baştan sıfıra sabitlenir. Böylece indirgenmiş paydalardan biri 2 çarpanı taşıdığında yönlendirme tek anlamlı olur. Eğer iki tarafta da 2 çarpanı yoksa, bu kez 5'in üslerinden biri de sıfıra sabitlenir ve kalan yer değiştirme simetrisi kaldırılır. Sonuç olarak döngüler tam olarak \(\bigl(1,2^\alpha5^\beta\bigr)\) ve \(\bigl(2^\alpha,5^\beta\bigr)\) ailelerini tekrar üretmeden dolaşır.

Bir adayı katkıya çevirmek

Her üs dörtlüsü için uygulama iki indirgenmiş paydayı yeniden kurar, \(2^{n-u-r}5^{n-v-s}\) ölçek çarpanını oluşturur ve

$$K=(x+y)2^{\,n-u-r}5^{\,n-v-s}$$

değerini hesaplar. Ardından \(K\), deneme bölmesiyle asal çarpanlarına ayrılır ve bu çarpan üslerinden \(\tau(K)\) elde edilir. Bu katkı o anki \(n\) için toplama eklenir; dış döngü de \(n=1\) ile \(9\) arasındaki tüm değerleri biriktirir. C++ ve Python sürümleri ayrıca sonucun öncesinde yayımlanan \(f(1)=20\) kontrolünü yapar.

Karmaşıklık Analizi

Sabit bir \(n\) için aday sayısı tam olarak küçüktür: \(\bigl(1,2^\alpha5^\beta\bigr)\) tipinde \((n+1)^2\) çift, \(\bigl(2^\alpha,5^\beta\bigr)\) tipinde \(n^2\) çift vardır. Bu nedenle tarama maliyeti her \(n\) için \(O(n^2)\) adaydır.

Her aday için \(K\) değeri deneme bölmesiyle asal çarpanlarına ayrılır; en kötü durumda maliyet \(O(\sqrt{K})\)'dir. Bu problemde \(K\) en fazla \(10^n\) mertebesindedir ve yalnızca \(n\le 9\) gerekir. Bu yüzden uygulamada süre çok küçüktür. Bellek kullanımı \(O(1)\)'dir; aynı anda yalnızca birkaç tamsayı tutulur.

Dipnotlar ve Referanslar

  1. Problem sayfası: https://projecteuler.net/problem=157
  2. Diofant denklemi: Wikipedia - Diophantine equation
  3. Bölen fonksiyonu: Wikipedia - Divisor function
  4. EBOB: Wikipedia - Greatest common divisor
  5. Aritmetiğin temel teoremi: Wikipedia - Fundamental theorem of arithmetic

Resumen del Problema

Sea \(f(n)\) el número de soluciones enteras positivas de

$$\frac{1}{a}+\frac{1}{b}=\frac{p}{10^n}.$$

La tarea de Project Euler es calcular

$$\sum_{n=1}^{9} f(n).$$

Aquí \(p\) no está fijado de antemano; también forma parte de la solución. Por eso el trabajo real consiste en describir qué pares \((a,b)\) son posibles y cuántos valores de \(p\) nacen de cada uno.

Una búsqueda directa es inviable porque \(a\) y \(b\) no tienen una cota previa útil. La solución rápida aparece al separar el factor común de \(a\) y \(b\), estudiar solo el núcleo coprimo restante y contar después todas sus extensiones mediante la función número de divisores.

Enfoque Matemático

La rigidez del problema aparece en cuanto se elimina el factor común: los denominadores reducidos solo pueden contener los primos 2 y 5, porque el denominador del lado derecho es \(10^n=2^n5^n\).

Separar el mcd

Escribimos

$$a=dx,\qquad b=dy,\qquad \gcd(x,y)=1.$$

Al sustituir en la ecuación obtenemos

$$\frac{1}{dx}+\frac{1}{dy}=\frac{x+y}{dxy}=\frac{p}{10^n},$$

y, al limpiar denominadores,

$$10^n(x+y)=pdxy.$$

Así, una vez fijado el par coprimo \((x,y)\), toda la libertad restante queda en \(d\) y en \(p\).

Por qué los denominadores reducidos deben dividir a \(10^n\)

Si un primo dividiera a la vez \(xy\) y \(x+y\), dividiría a uno de \(x\) o \(y\), y entonces, por dividir también a la suma, tendría que dividir al otro. Eso contradice \(\gcd(x,y)=1\). Por tanto

$$\gcd(xy,x+y)=1.$$

A partir de

$$10^n(x+y)=pdxy$$

se deduce que todos los factores primos de \(xy\) ya tienen que estar presentes en \(10^n\). Luego

$$xy\mid 10^n,$$

y por eso \(x\) e \(y\) solo pueden usar los primos 2 y 5. Podemos escribir

$$x=2^u5^v,\qquad y=2^r5^s,$$

con

$$u+r\le n,\qquad v+s\le n,\qquad \min(u,r)=0,\qquad \min(v,s)=0.$$

Las dos últimas condiciones expresan la coprimalidad: para cada primo, toda su potencia se queda en un lado o en el otro, pero no en ambos.

Pares reducidos canónicos

La ecuación es simétrica en \(a\) y \(b\), así que basta contar una sola orientación canónica del par reducido \((x,y)\). Como solo intervienen 2 y 5, todo par posible cae, salvo intercambio, en una de dos familias:

$$\bigl(1,2^\alpha5^\beta\bigr)\quad\text{con}\quad 0\le \alpha,\beta\le n,$$

o bien

$$\bigl(2^\alpha,5^\beta\bigr)\quad\text{con}\quad 1\le \alpha,\beta\le n.$$

La primera familia corresponde al caso en que un lado absorbe ambas potencias primas. La segunda corresponde al reparto puro, con una potencia de 2 a un lado y una potencia de 5 al otro. Esa es exactamente la reducción de simetría que implementa el código.

Cada par reducido aporta un número de divisores

Reordenando la ecuación principal, obtenemos

$$pd=\frac{10^n(x+y)}{xy}=(x+y)2^{\,n-u-r}5^{\,n-v-s}=:K.$$

Fijemos ahora un par coprimo válido \((x,y)\). Si \(d\) es cualquier divisor positivo de \(K\), entonces

$$a=dx,\qquad b=dy,\qquad p=\frac{K}{d}$$

produce una solución en enteros positivos. Y recíprocamente, toda solución con ese mismo par reducido obliga a que \(d\mid K\). Por tanto, el número de soluciones generado por un par canónico \((x,y)\) es exactamente

$$\tau(K),$$

donde \(\tau\) es la función número de divisores. El problema completo queda reducido a enumerar esos pares canónicos y sumar los correspondientes valores de \(\tau(K)\).

Ejemplo trabajado: \(n=1\)

Cuando \(n=1\), los pares reducidos canónicos son

$$ (1,1),\ (1,2),\ (1,5),\ (1,10),\ (2,5). $$

Los valores resultantes de \(K\) son

$$ 20,\ 15,\ 12,\ 11,\ 7, $$

y sus aportes son

$$ \tau(20)=6,\quad \tau(15)=4,\quad \tau(12)=6,\quad \tau(11)=2,\quad \tau(7)=2. $$

Así se obtiene

$$f(1)=6+4+6+2+2=20,$$

que coincide con el valor de control publicado. La interpretación con divisores se ve muy clara en \((x,y)=(1,1)\): como \(K=20\), cada divisor \(d\) de 20 da directamente la solución \((a,b,p)=(d,d,20/d)\).

Cómo Funciona el Código

Las implementaciones en C++, Python y Java no buscan directamente sobre \(a\), \(b\) ni \(p\). Recorren los exponentes de 2 y 5 que describen el par reducido canónico, calculan el valor correspondiente de \(K\) y añaden su número de divisores.

Enumeración de los patrones canónicos

Uno de los exponentes de 2 se fija en cero desde el principio. Con eso queda determinada una orientación única en cuanto uno de los denominadores reducidos contiene un factor 2. Si ninguno de los dos contiene 2, también se fija en cero uno de los exponentes de 5 para eliminar la simetría restante. En la práctica, esa estructura de bucles enumera exactamente las familias \(\bigl(1,2^\alpha5^\beta\bigr)\) y \(\bigl(2^\alpha,5^\beta\bigr)\) sin contar duplicados.

Convertir un candidato en una contribución

Para cada tupla de exponentes, la implementación reconstruye los dos denominadores reducidos, forma el factor de escala \(2^{n-u-r}5^{n-v-s}\) y evalúa

$$K=(x+y)2^{\,n-u-r}5^{\,n-v-s}.$$

Después factoriza \(K\) por división de prueba y transforma los exponentes primos en \(\tau(K)\). Ese valor se añade al total del \(n\) actual, y un bucle exterior acumula los resultados para \(n=1,\dots,9\). Las versiones de C++ y Python también comprueban antes el valor publicado \(f(1)=20\).

Análisis de Complejidad

Para un \(n\) fijo, el número de candidatos es pequeño y explícito: \((n+1)^2\) pares del tipo \(\bigl(1,2^\alpha5^\beta\bigr)\) y \(n^2\) pares del tipo \(\bigl(2^\alpha,5^\beta\bigr)\). Por tanto, la enumeración cuesta \(O(n^2)\) candidatos por cada \(n\).

Cada candidato requiere factorizar \(K\) mediante división de prueba, con coste \(O(\sqrt{K})\) en el peor caso. En este problema, \(K\) es como mucho del orden de \(10^n\), y el objetivo de Euler solo necesita \(n\le 9\). En consecuencia, el tiempo real es muy pequeño. El uso de memoria es \(O(1)\), ya que solo se mantienen unos pocos enteros a la vez.

Notas y Referencias

  1. Página del problema: https://projecteuler.net/problem=157
  2. Ecuación diofántica: Wikipedia - Diophantine equation
  3. Función divisor: Wikipedia - Divisor function
  4. Máximo común divisor: Wikipedia - Greatest common divisor
  5. Teorema fundamental de la aritmética: Wikipedia - Fundamental theorem of arithmetic

问题概述

设 \(f(n)\) 表示方程

$$\frac{1}{a}+\frac{1}{b}=\frac{p}{10^n}$$

的正整数解个数。Project Euler 157 要求计算

$$\sum_{n=1}^{9} f(n)$$

这里的 \(p\) 并不是预先给定的常数,而是解的一部分。真正要解决的问题,不是盲目搜索 \(a\) 和 \(b\),而是弄清楚哪些 \((a,b)\) 有可能出现,以及每个这样的分母对会对应多少个合法的 \(p\)。

如果直接枚举 \(a\) 和 \(b\),搜索空间没有自然上界,方法很快就会失控。有效做法是先把 \(a\) 与 \(b\) 的公因子剥离出来,只研究互素的“约化核心”,然后再用约数个数函数把所有可行的放大方式一次性数完。

数学方法

这道题的核心约束非常强:一旦把 \(a\) 与 \(b\) 的公因子提出,剩下的约化分母里只能出现质因子 2 和 5,因为右侧分母正是 \(10^n=2^n5^n\)。

先提出最大公因数

$$a=dx,\qquad b=dy,\qquad \gcd(x,y)=1$$

代入原式得到

$$\frac{1}{dx}+\frac{1}{dy}=\frac{x+y}{dxy}=\frac{p}{10^n},$$

清分母后变成

$$10^n(x+y)=pdxy$$

这样一来,只要互素对 \((x,y)\) 固定,剩下的自由度就只在公共因子 \(d\) 和分子 \(p\) 上。

为什么约化后的分母必须整除 \(10^n\)

如果某个质数同时整除 \(xy\) 与 \(x+y\),那么它必定整除 \(x\) 或 \(y\) 中的一个;又因为它整除和,所以它也会整除另一个,这就与 \(\gcd(x,y)=1\) 矛盾。因此

$$\gcd(xy,x+y)=1$$

再看

$$10^n(x+y)=pdxy,$$

由于 \(xy\) 与 \(x+y\) 互素,\(xy\) 的所有质因子都只能来自 \(10^n\)。所以

$$xy\mid 10^n,$$

于是 \(x\) 与 \(y\) 只能由 2 和 5 的幂构成。可写成

$$x=2^u5^v,\qquad y=2^r5^s,$$

并满足

$$u+r\le n,\qquad v+s\le n,\qquad \min(u,r)=0,\qquad \min(v,s)=0$$

最后两个条件正是互素性的表达:对于每个质数,它的全部指数要么落在左边,要么落在右边,不能同时分给两边。

约化对的规范形式

原方程对 \(a\) 与 \(b\) 是对称的,因此在约化到 \((x,y)\) 后,只需要为这对互素数选择一种规范顺序即可。由于允许出现的质数只有 2 和 5,所有约化对在交换顺序以后只会落入两类:

$$\bigl(1,2^\alpha5^\beta\bigr)\quad\text{其中}\quad 0\le \alpha,\beta\le n,$$

或者

$$\bigl(2^\alpha,5^\beta\bigr)\quad\text{其中}\quad 1\le \alpha,\beta\le n$$

第一类表示一边同时拿走 2 的幂和 5 的幂,另一边退化成 1。第二类表示真正的拆分情况,一边只有 2 的幂,另一边只有 5 的幂。实现中的循环结构,本质上就是把这种规范化后的两类情况无重复地枚举出来。

每个约化对都会贡献一个 \(\tau(K)\)

把主方程改写为

$$pd=\frac{10^n(x+y)}{xy}=(x+y)2^{\,n-u-r}5^{\,n-v-s}=:K$$

现在固定一个合法的互素约化对 \((x,y)\)。只要 \(d\) 是 \(K\) 的一个正约数,那么

$$a=dx,\qquad b=dy,\qquad p=\frac{K}{d}$$

就给出一个正整数解。反过来,凡是来自这个约化对的解,也必然满足 \(d\mid K\)。所以这个规范约化对贡献的解数恰好是

$$\tau(K),$$

其中 \(\tau\) 表示正约数个数函数。于是原问题就被压缩成一个很清晰的求和:枚举所有规范约化对,然后把对应的 \(\tau(K)\) 加起来。

具体例子:\(n=1\)

当 \(n=1\) 时,规范约化对只有

$$ (1,1),\ (1,2),\ (1,5),\ (1,10),\ (2,5) $$

它们对应的 \(K\) 分别是

$$ 20,\ 15,\ 12,\ 11,\ 7 $$

因此贡献为

$$ \tau(20)=6,\quad \tau(15)=4,\quad \tau(12)=6,\quad \tau(11)=2,\quad \tau(7)=2 $$

总和就是

$$f(1)=6+4+6+2+2=20,$$

这正好与题目给出的检验值一致。以 \((x,y)=(1,1)\) 为例,\(K=20\),所以 20 的每个正约数 \(d\) 都会直接产生一个解 \((a,b,p)=(d,d,20/d)\)。这个例子把“约数个数就是贡献”这一点展示得非常直观。

代码如何工作

C++、Python 和 Java 实现都不会直接枚举 \(a\)、\(b\) 或 \(p\)。它们只枚举决定规范约化对的 2 次幂和 5 次幂指数,计算相应的 \(K\),再把 \(K\) 的约数个数加入答案。

枚举规范指数模式

实现先把某一侧的 2 的指数固定为 0。这样只要另一侧带有 2 因子,方向就已经唯一确定了。如果两边都没有 2 因子,那么再把某一侧的 5 的指数也固定为 0,从而消掉剩余的交换对称性。经过这一步,循环实际上精确覆盖了 \(\bigl(1,2^\alpha5^\beta\bigr)\) 和 \(\bigl(2^\alpha,5^\beta\bigr)\) 这两类数学对象,而且不会重复计数。

把单个候选转成贡献

对每组指数,实现先还原两个约化分母,再构造缩放因子 \(2^{n-u-r}5^{n-v-s}\),然后计算

$$K=(x+y)2^{\,n-u-r}5^{\,n-v-s}$$

接着通过试除法分解 \(K\),根据质因子的指数求出 \(\tau(K)\)。这个值累加到当前 \(n\) 的计数中,外层循环再把 \(n=1\) 到 \(9\) 的结果全部加总。C++ 与 Python 实现还会先检查公开检验值 \(f(1)=20\) 是否成立。

复杂度分析

对固定的 \(n\),候选数量是显式可数的:\(\bigl(1,2^\alpha5^\beta\bigr)\) 这一类有 \((n+1)^2\) 个,\(\bigl(2^\alpha,5^\beta\bigr)\) 这一类有 \(n^2\) 个。因此枚举阶段的成本是每个 \(n\) 处理 \(O(n^2)\) 个候选。

每个候选都要对 \(K\) 做一次试除分解,最坏复杂度是 \(O(\sqrt{K})\)。在本题中,\(K\) 只在 \(10^n\) 的量级,而 Euler 目标只要求 \(n\le 9\),所以实际计算量很小。空间复杂度是 \(O(1)\),因为程序任意时刻只保留少数几个整数。

脚注与参考资料

  1. 题目页面:https://projecteuler.net/problem=157
  2. 丢番图方程:Wikipedia - Diophantine equation
  3. 约数函数:Wikipedia - Divisor function
  4. 最大公约数:Wikipedia - Greatest common divisor
  5. 算术基本定理:Wikipedia - Fundamental theorem of arithmetic

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

Пусть \(f(n)\) обозначает число положительных целочисленных решений уравнения

$$\frac{1}{a}+\frac{1}{b}=\frac{p}{10^n}.$$

В задаче Project Euler нужно вычислить

$$\sum_{n=1}^{9} f(n).$$

Число \(p\) заранее не задано: оно само входит в искомую тройку. Поэтому важно не просто перебирать \(a\) и \(b\), а понять, какие пары знаменателей вообще возможны и сколько различных значений \(p\) соответствует каждой такой паре.

Прямой перебор бесполезен, потому что естественной верхней границы для \(a\) и \(b\) нет. Рабочее решение сначала выделяет общий множитель из \(a\) и \(b\), затем изучает только взаимно простое ядро и, наконец, считает все его подъёмы через функцию числа делителей.

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

После выделения общего множителя структура задачи резко упрощается: в сокращённых знаменателях могут остаться только простые 2 и 5, потому что знаменатель справа равен \(10^n=2^n5^n\).

Выделение общего делителя

Положим

$$a=dx,\qquad b=dy,\qquad \gcd(x,y)=1.$$

Тогда исходное равенство принимает вид

$$\frac{1}{dx}+\frac{1}{dy}=\frac{x+y}{dxy}=\frac{p}{10^n},$$

а после избавления от знаменателей получаем

$$10^n(x+y)=pdxy.$$

Значит, при фиксированной взаимно простой паре \((x,y)\) вся оставшаяся свобода содержится только в \(d\) и \(p\).

Почему сокращённые знаменатели обязаны делить \(10^n\)

Если некоторый простой делит одновременно \(xy\) и \(x+y\), то, деля один из множителей \(x\) или \(y\), он будет делить и второй, потому что делит сумму. Это противоречит условию \(\gcd(x,y)=1\). Следовательно,

$$\gcd(xy,x+y)=1.$$

Из равенства

$$10^n(x+y)=pdxy$$

теперь следует, что все простые делители \(xy\) уже должны входить в \(10^n\). Иначе говоря,

$$xy\mid 10^n,$$

поэтому \(x\) и \(y\) состоят только из степеней 2 и 5. Их можно записать как

$$x=2^u5^v,\qquad y=2^r5^s,$$

где

$$u+r\le n,\qquad v+s\le n,\qquad \min(u,r)=0,\qquad \min(v,s)=0.$$

Последние два условия выражают взаимную простоту: для каждого простого вся его степень находится только слева или только справа.

Канонические сокращённые пары

Уравнение симметрично относительно \(a\) и \(b\), поэтому после перехода к \((x,y)\) достаточно считать только одну каноническую ориентацию пары. Так как доступны лишь простые 2 и 5, любая сокращённая пара с точностью до перестановки относится к одному из двух типов:

$$\bigl(1,2^\alpha5^\beta\bigr)\quad\text{при}\quad 0\le \alpha,\beta\le n,$$

или

$$\bigl(2^\alpha,5^\beta\bigr)\quad\text{при}\quad 1\le \alpha,\beta\le n.$$

Первый тип соответствует ситуации, когда одна сторона забирает и степени двойки, и степени пятёрки. Второй тип описывает настоящее разделение: одна сторона является чистой степенью 2, а другая чистой степенью 5. Именно такую редукцию симметрии реализуют программы.

Каждая сокращённая пара даёт вклад \(\tau(K)\)

Перепишем основное равенство так:

$$pd=\frac{10^n(x+y)}{xy}=(x+y)2^{\,n-u-r}5^{\,n-v-s}=:K.$$

Теперь зафиксируем допустимую взаимно простую пару \((x,y)\). Если \(d\) является любым положительным делителем числа \(K\), то

$$a=dx,\qquad b=dy,\qquad p=\frac{K}{d}$$

даёт положительное целочисленное решение. И наоборот, любое решение с этим сокращённым ядром обязано иметь \(d\mid K\). Значит, число решений, порождённых данным каноническим \((x,y)\), равно

$$\tau(K),$$

где \(\tau\) обозначает функцию числа положительных делителей. В итоге задача сводится к перечислению всех канонических сокращённых пар и суммированию соответствующих значений \(\tau(K)\).

Разобранный пример: \(n=1\)

При \(n=1\) канонические сокращённые пары таковы:

$$ (1,1),\ (1,2),\ (1,5),\ (1,10),\ (2,5). $$

Для них получаются значения

$$ 20,\ 15,\ 12,\ 11,\ 7 $$

для \(K\), а значит и вклады

$$ \tau(20)=6,\quad \tau(15)=4,\quad \tau(12)=6,\quad \tau(11)=2,\quad \tau(7)=2. $$

Следовательно,

$$f(1)=6+4+6+2+2=20,$$

что совпадает с опубликованной контрольной точкой. Особенно нагляден случай \((x,y)=(1,1)\): здесь \(K=20\), и каждый делитель \(d\) числа 20 напрямую создаёт решение \((a,b,p)=(d,d,20/d)\).

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

Реализации на C++, Python и Java не перебирают напрямую \(a\), \(b\) или \(p\). Вместо этого они перебирают показатели степеней 2 и 5, задающие каноническую сокращённую пару, вычисляют соответствующее \(K\) и добавляют число его делителей.

Перебор канонических схем показателей

Один из показателей степени двойки сразу фиксируется равным нулю. Благодаря этому ориентация пары становится однозначной, как только одна из сторон содержит множитель 2. Если же двойки нет ни на одной стороне, то ещё один показатель, уже для пятёрки, тоже фиксируется равным нулю, чтобы убрать оставшуюся симметрию при перестановке. В результате циклы перечисляют ровно семейства \(\bigl(1,2^\alpha5^\beta\bigr)\) и \(\bigl(2^\alpha,5^\beta\bigr)\) без повторов.

Преобразование кандидата во вклад

Для каждого набора показателей программа восстанавливает два сокращённых знаменателя, строит масштабный множитель \(2^{n-u-r}5^{n-v-s}\) и вычисляет

$$K=(x+y)2^{\,n-u-r}5^{\,n-v-s}.$$

Затем число \(K\) раскладывается пробным делением, а по показателям простых множителей находится \(\tau(K)\). Этот вклад добавляется к сумме для текущего \(n\), после чего внешний цикл накапливает результат для \(n=1,\dots,9\). В версиях на C++ и Python дополнительно проверяется опубликованное значение \(f(1)=20\).

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

Для фиксированного \(n\) число кандидатов невелико и явно вычисляется: \((n+1)^2\) пар типа \(\bigl(1,2^\alpha5^\beta\bigr)\) и \(n^2\) пар типа \(\bigl(2^\alpha,5^\beta\bigr)\). Значит, этап перечисления требует \(O(n^2)\) кандидатов на одно значение \(n\).

Для каждого кандидата нужно факторизовать \(K\) пробным делением, что в худшем случае стоит \(O(\sqrt{K})\). В данной задаче \(K\) имеет размер порядка \(10^n\), а нужно только \(n\le 9\), так что реальное время работы очень мало. Память имеет порядок \(O(1)\), потому что одновременно хранятся лишь несколько целых чисел.

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

  1. Страница задачи: https://projecteuler.net/problem=157
  2. Диофантово уравнение: Wikipedia - Diophantine equation
  3. Функция числа делителей: Wikipedia - Divisor function
  4. Наибольший общий делитель: Wikipedia - Greatest common divisor
  5. Основная теорема арифметики: Wikipedia - Fundamental theorem of arithmetic

ملخص المسألة

لتكن \(f(n)\) هي عدد الحلول الصحيحة الموجبة للمعادلة

$$\frac{1}{a}+\frac{1}{b}=\frac{p}{10^n}.$$

ومطلوب مسألة Project Euler هو حساب

$$\sum_{n=1}^{9} f(n).$$

المتغيّر \(p\) ليس قيمة ثابتة معطاة مسبقًا، بل هو جزء من الحل نفسه. لذلك فالمطلوب الحقيقي هو فهم أي الأزواج \((a,b)\) يمكن أن تظهر، وكم قيمة مختلفة لـ \(p\) تنتج من كل زوج منها.

البحث المباشر غير عملي، لأن \(a\) و\(b\) لا يملكان حدًا علويًا واضحًا منذ البداية. الفكرة الفعالة هي فصل العامل المشترك بين \(a\) و\(b\)، ثم دراسة النواة المختزلة المتباينة نسبيًا، وبعد ذلك عدّ جميع التوسعات الممكنة لهذه النواة بواسطة دالة عدد القواسم.

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

جوهر الحل أن البنية تصبح شديدة التقييد بعد إزالة العامل المشترك: فالمقامات المختزلة لا يمكن أن تحتوي إلا على العاملين الأوليين 2 و5، لأن مقام الطرف الأيمن هو \(10^n=2^n5^n\).

فصل القاسم المشترك الأكبر

نكتب

$$a=dx,\qquad b=dy,\qquad \gcd(x,y)=1.$$

بالتعويض نحصل على

$$\frac{1}{dx}+\frac{1}{dy}=\frac{x+y}{dxy}=\frac{p}{10^n},$$

ومن ثم بعد إزالة المقامات:

$$10^n(x+y)=pdxy.$$

إذًا إذا ثُبِّت الزوج المتباين نسبيًا \((x,y)\)، فإن الحرية الباقية كلها تصبح محصورة في \(d\) و\(p\).

لماذا يجب أن يقسم المقامان المختزلان \(10^n\)

إذا كان هناك عدد أولي يقسم \(xy\) ويقسم أيضًا \(x+y\)، فهو يقسم أحد \(x\) أو \(y\)، ثم لأنه يقسم المجموع سيقسم الآخر أيضًا، وهذا يناقض الشرط \(\gcd(x,y)=1\). لذلك

$$\gcd(xy,x+y)=1.$$

ومن العلاقة

$$10^n(x+y)=pdxy$$

نستنتج أن جميع العوامل الأولية في \(xy\) يجب أن تكون موجودة أصلًا في \(10^n\). أي إن

$$xy\mid 10^n,$$

ولذلك لا يمكن أن يتكوّن \(x\) و\(y\) إلا من قوى 2 و5:

$$x=2^u5^v,\qquad y=2^r5^s,$$

مع الشروط

$$u+r\le n,\qquad v+s\le n,\qquad \min(u,r)=0,\qquad \min(v,s)=0.$$

والشرطان الأخيران يعبّران عن التباين النسبي: فكل قوة أولية توضع كلها في طرف واحد أو في الطرف الآخر، ولا تتوزع على الجانبين.

الأزواج المختزلة القياسية

المعادلة متماثلة بالنسبة إلى \(a\) و\(b\)، لذلك يكفي بعد الاختزال إلى \((x,y)\) أن نعدّ ترتيبًا قياسيًا واحدًا فقط. وبما أن العوامل الأولية الممكنة محصورة في 2 و5، فإن كل زوج مختزل يقع، بعد تجاهل التبديل، في إحدى العائلتين الآتيتين:

$$\bigl(1,2^\alpha5^\beta\bigr), \qquad 0\le \alpha,\beta\le n$$

أو

$$\bigl(2^\alpha,5^\beta\bigr), \qquad 1\le \alpha,\beta\le n$$

العائلة الأولى تمثل الحالة التي يأخذ فيها أحد الطرفين قوى 2 وقوى 5 معًا. والعائلة الثانية تمثل حالة الانقسام الحقيقي، حيث يكون أحد الطرفين قوة خالصة للعدد 2 والآخر قوة خالصة للعدد 5. وهذا بالضبط هو كسر التناظر الذي تنفذه التطبيقات.

كل زوج مختزل يساهم بعدد قواسم

يمكن إعادة كتابة المعادلة الرئيسية بالشكل

$$pd=\frac{10^n(x+y)}{xy}=(x+y)2^{\,n-u-r}5^{\,n-v-s}=:K.$$

ثبّت الآن زوجًا مختزلًا صالحًا \((x,y)\). إذا كان \(d\) أي قاسم موجب لـ \(K\)، فإن

$$a=dx,\qquad b=dy,\qquad p=\frac{K}{d}$$

يعطي حلًا صحيحًا موجبًا. وبالعكس، كل حل يأتي من هذا الزوج المختزل لا بد أن يحقق \(d\mid K\). لذلك فإن عدد الحلول التي يولدها الزوج القياسي \((x,y)\) يساوي تمامًا

$$\tau(K),$$

حيث \(\tau\) هي دالة عدد القواسم الموجبة. وهكذا تتحول المسألة كلها إلى تعداد الأزواج القياسية المختزلة ثم جمع قيم \(\tau(K)\) المقابلة لها.

مثال مفصّل: \(n=1\)

عندما \(n=1\)، تكون الأزواج القياسية المختزلة هي

$$ (1,1),\ (1,2),\ (1,5),\ (1,10),\ (2,5). $$

وتكون قيم \(K\) المقابلة

$$ 20,\ 15,\ 12,\ 11,\ 7, $$

ومن ثم تكون المساهمات

$$ \tau(20)=6,\quad \tau(15)=4,\quad \tau(12)=6,\quad \tau(11)=2,\quad \tau(7)=2. $$

إذن

$$f(1)=6+4+6+2+2=20,$$

وهو تمامًا مقدار التحقق المنشور في نص المسألة. ويظهر معنى العد بواسطة القواسم بوضوح في الحالة \((x,y)=(1,1)\): إذ إن \(K=20\)، وكل قاسم موجب \(d\) للعدد 20 ينتج مباشرة الحل \((a,b,p)=(d,d,20/d)\).

كيف تعمل الشيفرة

تنفيذات C++ وPython وJava لا تبحث مباشرة في \(a\) أو \(b\) أو \(p\). بل تدور على أسس 2 و5 التي تحدد الزوج المختزل القياسي، ثم تحسب \(K\) الموافق وتضيف عدد قواسمه إلى المجموع.

تعداد الأنماط الأسّية القياسية

يُثبَّت أحد أسس العدد 2 على الصفر منذ البداية. بذلك يصبح الاتجاه فريدًا فور احتواء أحد المقامين المختزلين على عامل 2. وإذا لم يحمل أي طرف عامل 2، فيُثبَّت أيضًا أحد أسس العدد 5 على الصفر لإزالة تناظر التبديل المتبقي. وبهذه البنية تعدّ الحلقات عمليًا العائلتين \(\bigl(1,2^\alpha5^\beta\bigr)\) و\(\bigl(2^\alpha,5^\beta\bigr)\) من دون تكرار.

تحويل المرشح إلى مساهمة

لكل مجموعة من الأسس، تعيد الشيفرة بناء المقامين المختزلين، ثم تكوّن عامل القياس \(2^{n-u-r}5^{n-v-s}\)، وتحسب

$$K=(x+y)2^{\,n-u-r}5^{\,n-v-s}.$$

بعد ذلك تُفكَّك \(K\) بالقسمة التجريبية، وتُحوَّل أسس العوامل الأولية إلى \(\tau(K)\). تُضاف هذه القيمة إلى مجموع \(n\) الحالي، ثم تجمع الحلقة الخارجية النتائج من \(n=1\) حتى \(9\). كما أن تنفيذي C++ وPython يفحصان أولًا قيمة التحقق المنشورة \(f(1)=20\).

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

لـ \(n\) ثابت، عدد المرشحين صغير ويمكن كتابته صراحة: هناك \((n+1)^2\) زوجًا من النوع \(\bigl(1,2^\alpha5^\beta\bigr)\)، و\(n^2\) زوجًا من النوع \(\bigl(2^\alpha,5^\beta\bigr)\). لذلك فمرحلة التعداد تكلف \(O(n^2)\) مرشحًا لكل \(n\).

كل مرشح يتطلب تحليل \(K\) بالقسمة التجريبية، وتكلفته في أسوأ الأحوال \(O(\sqrt{K})\). لكن \(K\) هنا لا يتجاوز تقريبًا رتبة \(10^n\)، كما أن المسألة تحتاج فقط إلى \(n\le 9\)، لذا فالزمن العملي صغير جدًا. استهلاك الذاكرة هو \(O(1)\)، لأن البرنامج يحتفظ بعدد قليل فقط من القيم الصحيحة في كل لحظة.

الحواشي والمراجع

  1. صفحة المسألة: https://projecteuler.net/problem=157
  2. المعادلة الديوفانتية: Wikipedia - Diophantine equation
  3. دالة القواسم: Wikipedia - Divisor function
  4. القاسم المشترك الأكبر: Wikipedia - Greatest common divisor
  5. النظرية الأساسية في الحساب: Wikipedia - Fundamental theorem of arithmetic