Problem Summary

Let

$$T(r)=\#\left\{(x_1,x_2,x_3,x_4)\in\mathbb Z^4: x_1^2+x_2^2+x_3^2+x_4^2\le r^2\right\}.$$

The problem asks for this lattice-point count in four dimensions when \(r=10^8\), with the final value reduced modulo \(10^9+7\). A direct enumeration of all integer quadruples is hopeless, so the solution converts the geometry into a divisor sum that can be evaluated in about \(O(\sqrt{r^2})\) time.

Mathematical Approach

The key observation is that the hyperball can be counted shell by shell according to the squared distance from the origin.

Step 1: Turn the Hyperball into a Summatory Function

Set \(N=r^2\). For each integer \(n\ge 0\), let \(r_4(n)\) be the number of integer quadruples satisfying

$$x_1^2+x_2^2+x_3^2+x_4^2=n.$$

Every lattice point inside the ball has some squared radius \(n\) with \(0\le n\le N\), so

$$T(r)=\sum_{n=0}^{N} r_4(n).$$

This removes the geometric viewpoint and replaces it with a summation problem.

Step 2: Apply Jacobi's Four-Square Theorem

For \(n>0\), Jacobi's theorem gives

$$r_4(n)=8\sum_{\substack{d\mid n\\4\nmid d}} d,$$

and of course \(r_4(0)=1\). Substituting this into the previous identity yields

$$T(r)=1+8\sum_{n=1}^{N}\sum_{\substack{d\mid n\\4\nmid d}} d.$$

Now interchange the order of summation. A fixed divisor \(d\) contributes once for each multiple of \(d\) up to \(N\), so it appears exactly \(\left\lfloor N/d\right\rfloor\) times. Therefore

$$T(r)=1+8\sum_{\substack{d\le N\\4\nmid d}} d\left\lfloor\frac{N}{d}\right\rfloor.$$

Step 3: Remove the Multiples of 4 Cleanly

Introduce the summatory function

$$S(N)=\sum_{d=1}^{N} d\left\lfloor\frac{N}{d}\right\rfloor.$$

Then the terms with \(4\nmid d\) are obtained by subtracting the terms with \(d=4k\). Those discarded terms are

$$\sum_{k=1}^{\lfloor N/4\rfloor} 4k\left\lfloor\frac{N}{4k}\right\rfloor.$$

Since \(\left\lfloor N/(4k)\right\rfloor=\left\lfloor \left\lfloor N/4\right\rfloor /k\right\rfloor\), this becomes

$$4S\!\left(\left\lfloor\frac{N}{4}\right\rfloor\right).$$

Hence the whole problem collapses to the closed form

$$\boxed{T(r)=1+8\left(S(N)-4S\!\left(\left\lfloor\frac{N}{4}\right\rfloor\right)\right),\qquad N=r^2.}$$

Step 4: Evaluate \(S(N)\) in \(O(\sqrt N)\)

A naive evaluation of \(S(N)\) would still be linear in \(N\). The implementation avoids that by exploiting repeated values of \(\left\lfloor N/d\right\rfloor\).

Let

$$M=\left\lfloor\sqrt N\right\rfloor.$$

For the small divisors \(1\le d\le M\), compute the terms directly:

$$\sum_{d=1}^{M} d\left\lfloor\frac{N}{d}\right\rfloor.$$

For large divisors \(d>M\), group them by the common quotient

$$q=\left\lfloor\frac{N}{d}\right\rfloor.$$

All \(d\) producing the same \(q\) lie in the interval

$$L_q=\left\lfloor\frac{N}{q+1}\right\rfloor+1,\qquad R_q=\left\lfloor\frac{N}{q}\right\rfloor.$$

Only the portion above \(M\) belongs to the second half, so the effective lower bound is \(\max(M+1,L_q)\). The grouped contribution is then

$$q\sum_{d=\max(M+1,L_q)}^{R_q} d,$$

and the inner sum is an arithmetic progression:

$$\sum_{d=l}^{r} d=\frac{(l+r)(r-l+1)}{2}.$$

This split-hyperbola decomposition visits only about \(2\sqrt N\) meaningful ranges.

Step 5: Work Modulo \(10^9+7\)

The target answer is needed modulo

$$P=10^9+7.$$

So every addition and multiplication is reduced modulo \(P\). The division by \(2\) in the arithmetic-series formula is replaced by the modular inverse

$$2^{-1}\equiv 500000004 \pmod{P}.$$

Because the arithmetic-series sum is an exact integer before reduction, performing the reduction at every step preserves the correct final residue.

Worked Example: \(r=2\)

Here \(N=r^2=4\). First compute

$$S(4)=1\cdot 4+2\cdot 2+3\cdot 1+4\cdot 1=15.$$

Also, \(\left\lfloor N/4\right\rfloor=1\), so

$$S(1)=1.$$

Substituting into the closed form gives

$$T(2)=1+8(15-4\cdot 1)=1+8\cdot 11=89.$$

This matches the standard checkpoint for the problem and confirms that the divisor-sum reformulation is correct.

How the Code Works

The C++, Python, and Java implementations all evaluate the same formula

$$T(r)=1+8\left(S(r^2)-4S\!\left(\left\lfloor\frac{r^2}{4}\right\rfloor\right)\right)\pmod{10^9+7}.$$

Each implementation first computes an integer square root to split the summation for \(S(N)\) into a direct part and a grouped part. The direct part handles small divisors one by one. The grouped part iterates over quotient values \(q\), reconstructs the divisor interval that shares that quotient, clips the interval so that it stays strictly above \(\sqrt N\), and then adds the interval using the arithmetic-series formula.

The implementations keep every intermediate result modulo \(10^9+7\). The Python and Java versions partition the two summation phases across available worker tasks, while the C++ version performs the same mathematics in a single-threaded pass with careful wide-integer multiplication for safety. Despite those engineering differences, all three implementations are computing exactly the same divisor decomposition.

Complexity Analysis

For one evaluation of \(S(N)\), the direct loop has length \(\lfloor\sqrt N\rfloor\), and the grouped loop also runs over only \(O(\sqrt N)\) distinct quotient values. Therefore

$$S(N)\text{ can be evaluated in }O(\sqrt N)\text{ time}.$$

The final answer requires two such evaluations, namely at \(N=r^2\) and at \(\left\lfloor N/4\right\rfloor\), so the asymptotic running time remains \(O(\sqrt N)\). The serial method uses \(O(1)\) auxiliary memory, and the parallel variants add only modest task-management overhead on top of the same \(O(\sqrt N)\) total work.

Footnotes and References

  1. Problem page: https://projecteuler.net/problem=596
  2. Jacobi's four-square theorem: Wikipedia - Jacobi's four-square theorem
  3. Dirichlet hyperbola method: Wikipedia - Dirichlet hyperbola method
  4. Sum of squares function: Wikipedia - Sum of squares function
  5. Lattice point: Wikipedia - Lattice point

Problemzusammenfassung

Definiere

$$T(r)=\#\left\{(x_1,x_2,x_3,x_4)\in\mathbb Z^4: x_1^2+x_2^2+x_3^2+x_4^2\le r^2\right\}.$$

Gesucht ist also die Anzahl ganzzahliger Gitterpunkte im vierdimensionalen Ball mit Radius \(r\). Für die eigentliche Aufgabe wird \(r=10^8\) eingesetzt und das Ergebnis modulo \(10^9+7\) verlangt. Eine direkte Durchmusterung aller ganzzahligen Vierer-Tupel ist ausgeschlossen; deshalb wird das geometrische Problem in eine Divisorensumme umgeschrieben.

Mathematischer Ansatz

Der zentrale Trick besteht darin, die Punkte nach ihrem quadrierten Abstand vom Ursprung zu gruppieren.

Schritt 1: Vom Hyperball zu einer Summenfunktion

Setze \(N=r^2\). Für jedes \(n\ge 0\) bezeichne \(r_4(n)\) die Anzahl ganzzahliger Vierer-Tupel mit

$$x_1^2+x_2^2+x_3^2+x_4^2=n.$$

Jeder Gitterpunkt im Ball besitzt genau einen solchen Wert \(n\) mit \(0\le n\le N\). Daher gilt

$$T(r)=\sum_{n=0}^{N} r_4(n).$$

Damit ist die Geometrie auf eine arithmetische Summation zurückgeführt.

Schritt 2: Jacobi auf die Schalen anwenden

Für \(n>0\) liefert Jacobis Vier-Quadrate-Theorem

$$r_4(n)=8\sum_{\substack{d\mid n\\4\nmid d}} d,$$

und zusätzlich gilt \(r_4(0)=1\). Einsetzen ergibt

$$T(r)=1+8\sum_{n=1}^{N}\sum_{\substack{d\mid n\\4\nmid d}} d.$$

Nun werden die Summen vertauscht. Ein fester Divisor \(d\) tritt für alle Vielfachen von \(d\) bis \(N\) auf, also genau \(\left\lfloor N/d\right\rfloor\)-mal. Deshalb

$$T(r)=1+8\sum_{\substack{d\le N\\4\nmid d}} d\left\lfloor\frac{N}{d}\right\rfloor.$$

Schritt 3: Die durch 4 teilbaren Terme abspalten

Definiere die Summenfunktion

$$S(N)=\sum_{d=1}^{N} d\left\lfloor\frac{N}{d}\right\rfloor.$$

Dann erhält man die gesuchten Terme mit \(4\nmid d\), indem man die Beiträge der Form \(d=4k\) entfernt. Diese Beiträge sind

$$\sum_{k=1}^{\lfloor N/4\rfloor} 4k\left\lfloor\frac{N}{4k}\right\rfloor.$$

Wegen \(\left\lfloor N/(4k)\right\rfloor=\left\lfloor \left\lfloor N/4\right\rfloor /k\right\rfloor\) wird daraus

$$4S\!\left(\left\lfloor\frac{N}{4}\right\rfloor\right).$$

Somit folgt die geschlossene Formel

$$\boxed{T(r)=1+8\left(S(N)-4S\!\left(\left\lfloor\frac{N}{4}\right\rfloor\right)\right),\qquad N=r^2.}$$

Schritt 4: \(S(N)\) in \(O(\sqrt N)\) berechnen

Naiv wäre \(S(N)\) noch immer linear in \(N\). Die Lösung nutzt daher aus, dass der Quotient \(\left\lfloor N/d\right\rfloor\) viele Wiederholungen besitzt.

Setze

$$M=\left\lfloor\sqrt N\right\rfloor.$$

Für die kleinen Divisoren \(1\le d\le M\) summiert man direkt:

$$\sum_{d=1}^{M} d\left\lfloor\frac{N}{d}\right\rfloor.$$

Für große Divisoren \(d>M\) gruppiert man nach dem gemeinsamen Quotienten

$$q=\left\lfloor\frac{N}{d}\right\rfloor.$$

Alle \(d\) mit demselben \(q\) liegen im Intervall

$$L_q=\left\lfloor\frac{N}{q+1}\right\rfloor+1,\qquad R_q=\left\lfloor\frac{N}{q}\right\rfloor.$$

Für den zweiten Teil zählt nur der Bereich oberhalb von \(M\), also beginnt man effektiv bei \(\max(M+1,L_q)\). Der gesamte Gruppenbeitrag lautet damit

$$q\sum_{d=\max(M+1,L_q)}^{R_q} d,$$

wobei die innere Summe als arithmetische Reihe geschrieben wird:

$$\sum_{d=l}^{r} d=\frac{(l+r)(r-l+1)}{2}.$$

Genau diese Zerlegung macht die Laufzeit nahezu proportional zu \(\sqrt N\).

Schritt 5: Rechnen modulo \(10^9+7\)

Die Zielgröße wird nur modulo

$$P=10^9+7$$

benötigt. Deshalb werden alle Additionen und Multiplikationen fortlaufend modulo \(P\) reduziert. Die Division durch \(2\) in der Formel für die arithmetische Reihe wird durch das multiplikative Inverse

$$2^{-1}\equiv 500000004 \pmod{P}$$

ersetzt. Da die Reihensumme vor der Reduktion ganzzahlig ist, bleibt das Resultat modulo \(P\) exakt.

Durchgerechnetes Beispiel: \(r=2\)

Hier ist \(N=r^2=4\). Zunächst

$$S(4)=1\cdot 4+2\cdot 2+3\cdot 1+4\cdot 1=15.$$

Außerdem gilt \(\left\lfloor N/4\right\rfloor=1\), also

$$S(1)=1.$$

Damit folgt

$$T(2)=1+8(15-4\cdot 1)=1+8\cdot 11=89.$$

Das stimmt mit dem bekannten Kontrollwert überein und bestätigt die Umformung.

Wie der Code arbeitet

Die C++-, Python- und Java-Implementierungen werten alle dieselbe Formel aus, nämlich

$$T(r)=1+8\left(S(r^2)-4S\!\left(\left\lfloor\frac{r^2}{4}\right\rfloor\right)\right)\pmod{10^9+7}.$$

Zuerst wird eine ganzzahlige Quadratwurzel berechnet, um \(S(N)\) in einen direkten Teil und einen gruppierten Teil aufzuteilen. Der direkte Teil verarbeitet kleine Divisoren einzeln. Der gruppierte Teil läuft über die möglichen Quotienten \(q\), rekonstruiert das dazugehörige Divisorenintervall, schneidet es auf den Bereich oberhalb von \(\sqrt N\) zu und addiert den gesamten Block mit der Formel für die arithmetische Reihe.

Alle Zwischenwerte werden modulo \(10^9+7\) gehalten. Die Python- und Java-Implementierungen teilen die beiden Summationsphasen auf verfügbare Worker auf, während die C++-Implementierung dieselbe Mathematik seriell mit vorsichtiger Ganzzahlarithmetik ausführt. Inhaltlich berechnen alle drei Programme aber exakt dieselbe Zerlegung der Divisorensumme.

Komplexitätsanalyse

Eine Auswertung von \(S(N)\) benötigt \(O(\sqrt N)\) Zeit, weil sowohl der direkte Bereich bis \(\lfloor\sqrt N\rfloor\) als auch die Anzahl der unterschiedlichen Quotienten darüber nur diese Größenordnung haben. Für die Gesamtlösung werden \(S(N)\) und \(S(\lfloor N/4\rfloor)\) berechnet, daher bleibt die asymptotische Laufzeit \(O(\sqrt N)\). Die serielle Variante benötigt \(O(1)\) Zusatzspeicher; die parallelen Varianten haben darüber hinaus nur geringen Verwaltungsaufwand für ihre Aufgabenaufteilung.

Fußnoten und Quellen

  1. Problemseite: https://projecteuler.net/problem=596
  2. Jacobis Vier-Quadrate-Theorem: Wikipedia - Jacobi's four-square theorem
  3. Dirichlets Hyperbelmethode: Wikipedia - Dirichlet hyperbola method
  4. Quadratsummenfunktion: Wikipedia - Sum of squares function
  5. Gitterpunkt: Wikipedia - Lattice point

Problem Özeti

Şunu tanımlayalım:

$$T(r)=\#\left\{(x_1,x_2,x_3,x_4)\in\mathbb Z^4: x_1^2+x_2^2+x_3^2+x_4^2\le r^2\right\}.$$

Burada aranan değer, dört boyutta yarıçapı \(r\) olan hiperkürenin içinde kalan tüm tamsayı kafes noktalarının sayısıdır. Asıl görevde \(r=10^8\) için sonuç \(10^9+7\) modunda istenir. Doğrudan nokta taraması mümkün olmadığından çözüm, geometriyi bölen toplamına dönüştürür.

Matematiksel Yaklaşım

Temel fikir, noktaları orijine olan karesel uzaklıklarına göre kabuk kabuk saymaktır.

Adım 1: Hiperküreyi toplamsal bir probleme çevir

\(N=r^2\) olsun. Her \(n\ge 0\) için \(r_4(n)\),

$$x_1^2+x_2^2+x_3^2+x_4^2=n$$

eşitliğini sağlayan tamsayı dörtlülerinin sayısı olsun. O zaman hiperkürenin içindeki her nokta tam olarak bir \(n\) değerine karşılık gelir ve

$$T(r)=\sum_{n=0}^{N} r_4(n)$$

olur. Böylece geometrik sayım aritmetik bir toplam haline gelir.

Adım 2: Jacobi'nin dört kare teoremini uygula

\(n>0\) için Jacobi teoremi

$$r_4(n)=8\sum_{\substack{d\mid n\\4\nmid d}} d$$

sonucunu verir; ayrıca \(r_4(0)=1\) olur. Bunu yerine yazarsak

$$T(r)=1+8\sum_{n=1}^{N}\sum_{\substack{d\mid n\\4\nmid d}} d$$

elde edilir. Şimdi toplamların yerini değiştiririz. Sabit bir \(d\), \(N\)'ye kadar olan katları için tam olarak \(\left\lfloor N/d\right\rfloor\) kez görünür. Dolayısıyla

$$T(r)=1+8\sum_{\substack{d\le N\\4\nmid d}} d\left\lfloor\frac{N}{d}\right\rfloor$$

olur.

Adım 3: 4'ün katlarını temiz biçimde ayır

Şimdi

$$S(N)=\sum_{d=1}^{N} d\left\lfloor\frac{N}{d}\right\rfloor$$

fonksiyonunu tanımlayalım. \(4\nmid d\) koşulunu uygulamak için \(d=4k\) olan terimleri çıkarırız. Bunlar

$$\sum_{k=1}^{\lfloor N/4\rfloor} 4k\left\lfloor\frac{N}{4k}\right\rfloor$$

şeklindedir. Ayrıca

$$\left\lfloor\frac{N}{4k}\right\rfloor=\left\lfloor \frac{\left\lfloor N/4\right\rfloor}{k}\right\rfloor$$

olduğundan bu toplam tam olarak

$$4S\!\left(\left\lfloor\frac{N}{4}\right\rfloor\right)$$

eder. Böylece kapalı formül

$$\boxed{T(r)=1+8\left(S(N)-4S\!\left(\left\lfloor\frac{N}{4}\right\rfloor\right)\right),\qquad N=r^2}$$

olarak bulunur.

Adım 4: \(S(N)\) değerini \(O(\sqrt N)\) zamanda hesapla

\(S(N)\)'yi doğrudan toplamak hâlâ çok pahalıdır. Bunun yerine \(\left\lfloor N/d\right\rfloor\) bölümünün uzun aralıklar boyunca sabit kalmasından yararlanılır.

Şunu alalım:

$$M=\left\lfloor\sqrt N\right\rfloor.$$

Küçük bölenler için doğrudan toplarız:

$$\sum_{d=1}^{M} d\left\lfloor\frac{N}{d}\right\rfloor.$$

Büyük bölenlerde ise

$$q=\left\lfloor\frac{N}{d}\right\rfloor$$

sabit kalan aralıklar kullanılır. Aynı \(q\) değerini veren tüm \(d\)'ler

$$L_q=\left\lfloor\frac{N}{q+1}\right\rfloor+1,\qquad R_q=\left\lfloor\frac{N}{q}\right\rfloor$$

aralığındadır. İkinci kısım yalnızca \(M\)'den büyük bölenleri içerdiği için alt sınır fiilen \(\max(M+1,L_q)\) olur. Grup katkısı da

$$q\sum_{d=\max(M+1,L_q)}^{R_q} d$$

şeklinde yazılır. İç toplam bir aritmetik dizi toplamıdır:

$$\sum_{d=l}^{r} d=\frac{(l+r)(r-l+1)}{2}.$$

Bu düzenleme yaklaşık \(2\sqrt N\) anlamlı aralıkla işi bitirir.

Adım 5: \(10^9+7\) modunda ilerle

Sonuç sadece

$$P=10^9+7$$

modunda gerektiği için, tüm toplama ve çarpma işlemleri sürekli mod \(P\) altında tutulur. Aritmetik dizi formülündeki \(2\)'ye bölme işlemi, modüler ters kullanılarak

$$2^{-1}\equiv 500000004 \pmod{P}$$

ile yapılır. Toplamın tam sayı olması sayesinde ara adımlarda mod almak nihai kalanı bozmaz.

Çalışılmış Örnek: \(r=2\)

Bu durumda \(N=r^2=4\). Önce

$$S(4)=1\cdot 4+2\cdot 2+3\cdot 1+4\cdot 1=15$$

bulunur. Ayrıca \(\left\lfloor N/4\right\rfloor=1\) olduğundan

$$S(1)=1.$$

Kapalı formüle yerleştirince

$$T(2)=1+8(15-4\cdot 1)=1+8\cdot 11=89$$

elde edilir. Bu, problemin bilinen küçük doğrulama değeridir.

Kod Nasıl Çalışır

C++, Python ve Java implementasyonları aynı matematiksel ifadeyi hesaplar:

$$T(r)=1+8\left(S(r^2)-4S\!\left(\left\lfloor\frac{r^2}{4}\right\rfloor\right)\right)\pmod{10^9+7}.$$

Önce tam sayı karekök bulunur ve \(S(N)\) hesabı iki parçaya ayrılır. İlk parça küçük bölenleri tek tek toplar. İkinci parça, bölüm değeri aynı kalan \(q\) gruplarını dolaşır; bu grupların bölen aralığı yeniden kurulur, aralık \(\sqrt N\)'nin üstünde kalacak şekilde kırpılır ve aritmetik dizi formülüyle tek adımda eklenir.

Tüm ara sonuçlar mod \(10^9+7\) altında tutulur. Python ve Java implementasyonları bu iki toplama aşamasını uygun işçilere bölerek paralelleştirir; C++ implementasyonu ise aynı hesabı tek iş parçacığında güvenli geniş tamsayı çarpımlarıyla yürütür. Matematiksel olarak üçü de aynı bölen ayrışımını uygular.

Karmaşıklık Analizi

Bir \(S(N)\) hesabında hem doğrudan bölüm hem de gruplanmış bölüm yalnızca \(O(\sqrt N)\) büyüklüğündedir; dolayısıyla süre karmaşıklığı \(O(\sqrt N)\) olur. Son cevapta \(S(N)\) ve \(S(\lfloor N/4\rfloor)\) hesaplandığı için toplam asimptotik süre değişmez. Seri yaklaşım \(O(1)\) ek bellek kullanır; paralel sürümlerde buna ek olarak yalnızca küçük görev yönetim maliyetleri vardır.

Dipnotlar ve Kaynaklar

  1. Problem sayfası: https://projecteuler.net/problem=596
  2. Jacobi'nin dört kare teoremi: Wikipedia - Jacobi's four-square theorem
  3. Dirichlet hiperbol yöntemi: Wikipedia - Dirichlet hyperbola method
  4. Kareler toplamı fonksiyonu: Wikipedia - Sum of squares function
  5. Kafes noktası: Wikipedia - Lattice point

Resumen del Problema

Definimos

$$T(r)=\#\left\{(x_1,x_2,x_3,x_4)\in\mathbb Z^4: x_1^2+x_2^2+x_3^2+x_4^2\le r^2\right\}.$$

Hay que contar, por tanto, cuántos puntos de la red entera en cuatro dimensiones caen dentro de la hiperesfera de radio \(r\). En el desafío real se toma \(r=10^8\) y se pide la respuesta módulo \(10^9+7\). Enumerar directamente todos los cuádruples enteros es inviable, así que la solución transforma el problema geométrico en una suma sobre divisores.

Enfoque Matemático

La idea central es contar la hiperesfera capa por capa según la distancia cuadrada al origen.

Paso 1: Convertir la hiperesfera en una función sumatoria

Sea \(N=r^2\). Para cada entero \(n\ge 0\), denotemos por \(r_4(n)\) el número de cuádruples enteros tales que

$$x_1^2+x_2^2+x_3^2+x_4^2=n.$$

Cada punto de la red dentro de la bola corresponde exactamente a un valor \(n\) con \(0\le n\le N\). Por ello,

$$T(r)=\sum_{n=0}^{N} r_4(n).$$

Así, el conteo geométrico se convierte en un problema aritmético.

Paso 2: Aplicar el teorema de Jacobi sobre cuatro cuadrados

Para \(n>0\), el teorema de Jacobi afirma que

$$r_4(n)=8\sum_{\substack{d\mid n\\4\nmid d}} d,$$

mientras que \(r_4(0)=1\). Sustituyendo en la expresión anterior se obtiene

$$T(r)=1+8\sum_{n=1}^{N}\sum_{\substack{d\mid n\\4\nmid d}} d.$$

Ahora intercambiamos el orden de las sumas. Un divisor fijo \(d\) contribuye para cada múltiplo suyo hasta \(N\), es decir, exactamente \(\left\lfloor N/d\right\rfloor\) veces. Entonces

$$T(r)=1+8\sum_{\substack{d\le N\\4\nmid d}} d\left\lfloor\frac{N}{d}\right\rfloor.$$

Paso 3: Separar los múltiplos de 4

Introduzcamos la función

$$S(N)=\sum_{d=1}^{N} d\left\lfloor\frac{N}{d}\right\rfloor.$$

Los términos prohibidos son exactamente aquellos con \(d=4k\). Su contribución es

$$\sum_{k=1}^{\lfloor N/4\rfloor} 4k\left\lfloor\frac{N}{4k}\right\rfloor.$$

Como \(\left\lfloor N/(4k)\right\rfloor=\left\lfloor \left\lfloor N/4\right\rfloor /k\right\rfloor\), esa suma se reescribe como

$$4S\!\left(\left\lfloor\frac{N}{4}\right\rfloor\right).$$

Por tanto, llegamos a la fórmula cerrada

$$\boxed{T(r)=1+8\left(S(N)-4S\!\left(\left\lfloor\frac{N}{4}\right\rfloor\right)\right),\qquad N=r^2.}$$

Paso 4: Evaluar \(S(N)\) en \(O(\sqrt N)\)

Calcular \(S(N)\) término a término seguiría siendo demasiado costoso. La mejora consiste en observar que el cociente \(\left\lfloor N/d\right\rfloor\) repite muchos valores.

Tomemos

$$M=\left\lfloor\sqrt N\right\rfloor.$$

Para los divisores pequeños \(1\le d\le M\), la suma se evalúa directamente:

$$\sum_{d=1}^{M} d\left\lfloor\frac{N}{d}\right\rfloor.$$

Para los divisores grandes \(d>M\), agrupamos por el cociente común

$$q=\left\lfloor\frac{N}{d}\right\rfloor.$$

Todos los \(d\) que producen el mismo \(q\) forman el intervalo

$$L_q=\left\lfloor\frac{N}{q+1}\right\rfloor+1,\qquad R_q=\left\lfloor\frac{N}{q}\right\rfloor.$$

En la segunda mitad solo cuentan los divisores por encima de \(M\), así que el límite inferior real es \(\max(M+1,L_q)\). La contribución agrupada pasa a ser

$$q\sum_{d=\max(M+1,L_q)}^{R_q} d,$$

y la suma interior se cierra con la fórmula de progresión aritmética

$$\sum_{d=l}^{r} d=\frac{(l+r)(r-l+1)}{2}.$$

Paso 5: Trabajar módulo \(10^9+7\)

La respuesta solo se necesita módulo

$$P=10^9+7.$$

Por eso cada suma y cada producto se reducen módulo \(P\). La división entre \(2\) que aparece en la progresión aritmética se reemplaza por el inverso modular

$$2^{-1}\equiv 500000004 \pmod{P}.$$

Como la suma de una progresión aritmética es un entero exacto antes de modular, esta reducción paso a paso conserva el residuo correcto.

Ejemplo Desarrollado: \(r=2\)

Aquí \(N=r^2=4\). Primero

$$S(4)=1\cdot 4+2\cdot 2+3\cdot 1+4\cdot 1=15.$$

Además, \(\left\lfloor N/4\right\rfloor=1\), así que

$$S(1)=1.$$

Entonces

$$T(2)=1+8(15-4\cdot 1)=1+8\cdot 11=89.$$

Este valor coincide con el punto de control pequeño del problema y muestra que la reformulación es correcta.

Cómo Funciona el Código

Las implementaciones en C++, Python y Java evalúan exactamente la misma identidad:

$$T(r)=1+8\left(S(r^2)-4S\!\left(\left\lfloor\frac{r^2}{4}\right\rfloor\right)\right)\pmod{10^9+7}.$$

Cada implementación calcula primero una raíz cuadrada entera para dividir el trabajo de \(S(N)\) en una parte directa y otra agrupada. La parte directa recorre uno a uno los divisores pequeños. La parte agrupada itera sobre los posibles valores de \(q\), reconstruye el intervalo de divisores que comparten ese cociente, recorta el intervalo para quedarse solo con los divisores mayores que \(\sqrt N\), y suma todo el bloque con la fórmula de progresión aritmética.

Todos los valores intermedios se mantienen módulo \(10^9+7\). Las versiones de Python y Java reparten las dos fases de suma entre varios trabajadores disponibles, mientras que la versión de C++ hace el mismo cálculo en una sola pasada con aritmética entera ancha para evitar problemas de rango. Desde el punto de vista matemático, las tres versiones implementan la misma descomposición por divisores.

Análisis de Complejidad

Una evaluación de \(S(N)\) requiere \(O(\sqrt N)\) operaciones, porque la parte directa llega hasta \(\lfloor\sqrt N\rfloor\) y la parte agrupada solo recorre \(O(\sqrt N)\) cocientes distintos. La solución final necesita dos evaluaciones, \(S(N)\) y \(S(\lfloor N/4\rfloor)\), por lo que la complejidad asintótica total sigue siendo \(O(\sqrt N)\). La versión secuencial usa \(O(1)\) memoria auxiliar, y las versiones paralelas solo añaden una pequeña sobrecarga de planificación.

Notas y Referencias

  1. Página del problema: https://projecteuler.net/problem=596
  2. Teorema de Jacobi sobre cuatro cuadrados: Wikipedia - Jacobi's four-square theorem
  3. Método de la hipérbola de Dirichlet: Wikipedia - Dirichlet hyperbola method
  4. Función suma de cuadrados: Wikipedia - Sum of squares function
  5. Punto de red: Wikipedia - Lattice point

问题概述

定义

$$T(r)=\#\left\{(x_1,x_2,x_3,x_4)\in\mathbb Z^4: x_1^2+x_2^2+x_3^2+x_4^2\le r^2\right\}.$$

也就是说,我们要统计四维空间中所有位于半径为 \(r\) 的超球内部的整数格点个数。原题要求在 \(r=10^8\) 时求出这个数量,并对 \(10^9+7\) 取模。若直接枚举所有整数四元组,规模完全不可接受,因此解法必须把几何计数改写成更适合数论处理的形式。

数学方法

核心思想是按照点到原点的平方距离,把整个四维超球拆成一层一层的“球壳”来计数。

步骤 1:把超球计数改写成求和问题

令 \(N=r^2\)。对每个整数 \(n\ge 0\),记 \(r_4(n)\) 为满足

$$x_1^2+x_2^2+x_3^2+x_4^2=n$$

的整数四元组个数。超球内部的每个格点都恰好对应某个 \(0\le n\le N\) 的平方距离,因此

$$T(r)=\sum_{n=0}^{N} r_4(n).$$

这样一来,原来的几何问题就被转化成了一个关于四平方表示数的求和问题。

步骤 2:使用 Jacobi 四平方定理

对 \(n>0\),Jacobi 四平方定理给出

$$r_4(n)=8\sum_{\substack{d\mid n\\4\nmid d}} d,$$

而 \(r_4(0)=1\)。代回上一式可得

$$T(r)=1+8\sum_{n=1}^{N}\sum_{\substack{d\mid n\\4\nmid d}} d.$$

接下来交换求和顺序。固定一个除数 \(d\),它会对所有不超过 \(N\) 的 \(d\) 的倍数贡献一次,因此总共出现

$$\left\lfloor\frac{N}{d}\right\rfloor$$

次。于是

$$T(r)=1+8\sum_{\substack{d\le N\\4\nmid d}} d\left\lfloor\frac{N}{d}\right\rfloor.$$

到这里,问题已经从“点是否在球内”变成了“带权除数求和”。

步骤 3:把 4 的倍数项单独剥离

定义一个辅助求和函数

$$S(N)=\sum_{d=1}^{N} d\left\lfloor\frac{N}{d}\right\rfloor.$$

那么只保留 \(4\nmid d\) 的项,就等于从全部项中减去 \(d=4k\) 的部分。被减掉的部分是

$$\sum_{k=1}^{\lfloor N/4\rfloor} 4k\left\lfloor\frac{N}{4k}\right\rfloor.$$

由于

$$\left\lfloor\frac{N}{4k}\right\rfloor=\left\lfloor \frac{\left\lfloor N/4\right\rfloor}{k}\right\rfloor,$$

所以上式恰好等于

$$4S\!\left(\left\lfloor\frac{N}{4}\right\rfloor\right).$$

于是整个题目的主公式就化为

$$\boxed{T(r)=1+8\left(S(N)-4S\!\left(\left\lfloor\frac{N}{4}\right\rfloor\right)\right),\qquad N=r^2.}$$

这一步非常关键,因为它把四平方表示数的求和彻底压缩成了两个同类型的求和函数。

步骤 4:用 \(O(\sqrt N)\) 计算 \(S(N)\)

如果逐项计算 \(S(N)\),仍然需要 \(O(N)\) 时间。真正的加速来自于观察到

$$\left\lfloor\frac{N}{d}\right\rfloor$$

在很长的一段区间内会保持不变。

$$M=\left\lfloor\sqrt N\right\rfloor.$$

当 \(1\le d\le M\) 时,直接累加

$$\sum_{d=1}^{M} d\left\lfloor\frac{N}{d}\right\rfloor.$$

当 \(d>M\) 时,不再按除数逐个处理,而是按商值

$$q=\left\lfloor\frac{N}{d}\right\rfloor$$

分组。所有产生同一个 \(q\) 的除数 \(d\) 都落在区间

$$L_q=\left\lfloor\frac{N}{q+1}\right\rfloor+1,\qquad R_q=\left\lfloor\frac{N}{q}\right\rfloor.$$

由于第二部分只负责 \(d>M\) 的那些项,所以实际下界要改成 \(\max(M+1,L_q)\)。对应的一整组贡献为

$$q\sum_{d=\max(M+1,L_q)}^{R_q} d.$$

而区间和可以用等差数列公式一次完成:

$$\sum_{d=l}^{r} d=\frac{(l+r)(r-l+1)}{2}.$$

这样就不再需要遍历所有 \(d\),而只需要遍历大约 \(2\sqrt N\) 个有意义的区间,因此总时间复杂度下降到 \(O(\sqrt N)\)。

步骤 5:在模 \(10^9+7\) 下稳定计算

题目最终只要求模

$$P=10^9+7$$

的结果,所以实现中会在每一步都对 \(P\) 取模。等差数列求和公式中的除以 \(2\),通过模逆元来完成:

$$2^{-1}\equiv 500000004 \pmod{P}.$$

因为区间和在取模之前本来就是精确整数,所以把加法、乘法和除法都搬到模运算下处理,不会改变最终答案的同余类。

例子:\(r=2\)

这是一个非常适合手算的检查点。此时 \(N=r^2=4\)。先算

$$S(4)=1\cdot 4+2\cdot 2+3\cdot 1+4\cdot 1=15.$$

再算

$$\left\lfloor\frac{N}{4}\right\rfloor=1,\qquad S(1)=1.$$

代入主公式:

$$T(2)=1+8(15-4\cdot 1)=1+8\cdot 11=89.$$

这正是该题的小规模校验值,因此说明推导和实现方向都是正确的。

代码如何工作

C++、Python 和 Java 三个实现都围绕同一个公式展开:

$$T(r)=1+8\left(S(r^2)-4S\!\left(\left\lfloor\frac{r^2}{4}\right\rfloor\right)\right)\pmod{10^9+7}.$$

实现时,首先计算整数平方根,把 \(S(N)\) 的求和分成两段。前一段逐个处理较小的除数。后一段不再直接枚举除数,而是枚举可能的商值 \(q\),据此反推出所有对应除数构成的连续区间,然后用等差数列求和公式把整段一次加入。区间的下界会被裁到 \(\sqrt N\) 以上,以避免与前一段重复。

所有中间结果都持续按 \(10^9+7\) 取模。Python 和 Java 实现把“直接求和”和“按商分组求和”这两部分再分配给多个工作任务,以利用多核;C++ 实现则保持单线程,但用足够宽的整数乘法来确保模乘安全。尽管工程细节略有不同,三种实现计算的都是同一套除数分组公式。

复杂度分析

单次计算 \(S(N)\) 时,直接部分需要处理 \(\lfloor\sqrt N\rfloor\) 项,而分组部分也只会遍历 \(O(\sqrt N)\) 个不同的商值,因此总时间复杂度为 \(O(\sqrt N)\)。最终答案需要分别计算 \(S(N)\) 与 \(S(\lfloor N/4\rfloor)\),但这不会改变渐近阶。串行版本的额外空间复杂度为 \(O(1)\),并行版本只是在此基础上增加少量任务管理开销。

注释与参考资料

  1. 题目页面: https://projecteuler.net/problem=596
  2. Jacobi 四平方定理: Wikipedia - Jacobi's four-square theorem
  3. Dirichlet 双曲线方法: Wikipedia - Dirichlet hyperbola method
  4. 平方和函数: Wikipedia - Sum of squares function
  5. 格点: Wikipedia - Lattice point

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

Определим

$$T(r)=\#\left\{(x_1,x_2,x_3,x_4)\in\mathbb Z^4: x_1^2+x_2^2+x_3^2+x_4^2\le r^2\right\}.$$

Нужно посчитать число целочисленных точек в четырёхмерном шаре радиуса \(r\). В самой задаче берётся \(r=10^8\), а ответ требуется по модулю \(10^9+7\). Полный перебор целочисленных четвёрок невозможен, поэтому решение переводит геометрический вопрос в арифметическую сумму по делителям.

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

Главная идея состоит в том, чтобы считать точки не напрямую, а по слоям с фиксированным квадратом расстояния до начала координат.

Шаг 1: Перейти от гипершара к суммирующей функции

Положим \(N=r^2\). Для каждого \(n\ge 0\) обозначим через \(r_4(n)\) количество целочисленных четвёрок, удовлетворяющих

$$x_1^2+x_2^2+x_3^2+x_4^2=n.$$

Каждая точка внутри шара имеет единственное такое значение \(n\), причём \(0\le n\le N\). Следовательно,

$$T(r)=\sum_{n=0}^{N} r_4(n).$$

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

Шаг 2: Применить теорему Якоби о четырёх квадратах

Для \(n>0\) теорема Якоби даёт формулу

$$r_4(n)=8\sum_{\substack{d\mid n\\4\nmid d}} d,$$

а также \(r_4(0)=1\). Подставляя это в предыдущую сумму, получаем

$$T(r)=1+8\sum_{n=1}^{N}\sum_{\substack{d\mid n\\4\nmid d}} d.$$

Теперь меняем порядок суммирования. Фиксированный делитель \(d\) встречается у всех кратных \(d\), не превосходящих \(N\), то есть ровно

$$\left\lfloor\frac{N}{d}\right\rfloor$$

раз. Поэтому

$$T(r)=1+8\sum_{\substack{d\le N\\4\nmid d}} d\left\lfloor\frac{N}{d}\right\rfloor.$$

Шаг 3: Отделить слагаемые, кратные 4

Введём функцию

$$S(N)=\sum_{d=1}^{N} d\left\lfloor\frac{N}{d}\right\rfloor.$$

Тогда нужная сумма по \(d\), не делящимся на \(4\), получается вычитанием вкладов \(d=4k\). Эти вклады равны

$$\sum_{k=1}^{\lfloor N/4\rfloor} 4k\left\lfloor\frac{N}{4k}\right\rfloor.$$

Поскольку

$$\left\lfloor\frac{N}{4k}\right\rfloor=\left\lfloor \frac{\left\lfloor N/4\right\rfloor}{k}\right\rfloor,$$

эта сумма точно совпадает с

$$4S\!\left(\left\lfloor\frac{N}{4}\right\rfloor\right).$$

Итак, получаем основную формулу задачи:

$$\boxed{T(r)=1+8\left(S(N)-4S\!\left(\left\lfloor\frac{N}{4}\right\rfloor\right)\right),\qquad N=r^2.}$$

Шаг 4: Вычислить \(S(N)\) за \(O(\sqrt N)\)

Если суммировать \(S(N)\) напрямую, получится линейный алгоритм. Ускорение возникает из-за того, что значение

$$\left\lfloor\frac{N}{d}\right\rfloor$$

много раз повторяется.

Положим

$$M=\left\lfloor\sqrt N\right\rfloor.$$

Для малых делителей \(1\le d\le M\) слагаемые считаются напрямую:

$$\sum_{d=1}^{M} d\left\lfloor\frac{N}{d}\right\rfloor.$$

Для больших делителей \(d>M\) элементы группируются по общему частному

$$q=\left\lfloor\frac{N}{d}\right\rfloor.$$

Все \(d\), соответствующие одному и тому же \(q\), образуют отрезок

$$L_q=\left\lfloor\frac{N}{q+1}\right\rfloor+1,\qquad R_q=\left\lfloor\frac{N}{q}\right\rfloor.$$

Во второй части нужны только \(d>M\), поэтому реальная нижняя граница равна \(\max(M+1,L_q)\). Вклад целого блока записывается так:

$$q\sum_{d=\max(M+1,L_q)}^{R_q} d.$$

Внутренняя сумма вычисляется формулой арифметической прогрессии:

$$\sum_{d=l}^{r} d=\frac{(l+r)(r-l+1)}{2}.$$

Благодаря этому приходится обрабатывать только порядка \(2\sqrt N\) существенных диапазонов.

Шаг 5: Все вычисления вести по модулю \(10^9+7\)

Ответ нужен по модулю

$$P=10^9+7.$$

Поэтому все промежуточные сложения и умножения немедленно приводятся по модулю \(P\). Деление на \(2\) в формуле суммы арифметической прогрессии заменяется на умножение на обратный элемент

$$2^{-1}\equiv 500000004 \pmod{P}.$$

Так как сама сумма прогрессии до взятия модуля является точным целым числом, такая замена полностью корректна.

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

Здесь \(N=r^2=4\). Сначала вычислим

$$S(4)=1\cdot 4+2\cdot 2+3\cdot 1+4\cdot 1=15.$$

Далее \(\left\lfloor N/4\right\rfloor=1\), значит

$$S(1)=1.$$

Подставляем в основную формулу:

$$T(2)=1+8(15-4\cdot 1)=1+8\cdot 11=89.$$

Это совпадает с известной контрольной точкой и служит хорошей проверкой вывода.

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

Реализации на C++, Python и Java вычисляют одну и ту же формулу:

$$T(r)=1+8\left(S(r^2)-4S\!\left(\left\lfloor\frac{r^2}{4}\right\rfloor\right)\right)\pmod{10^9+7}.$$

Сначала находится целая квадратная корень, чтобы разбить вычисление \(S(N)\) на две части. Первая часть перебирает малые делители по одному. Вторая часть проходит по возможным значениям частного \(q\), восстанавливает интервал делителей с таким частным, обрезает его так, чтобы он лежал строго выше \(\sqrt N\), и добавляет вклад всего интервала через формулу арифметической прогрессии.

Все промежуточные значения сохраняются по модулю \(10^9+7\). Реализации на Python и Java дополнительно делят обе фазы суммирования между доступными рабочими задачами, а реализация на C++ выполняет те же вычисления последовательно, используя достаточно широкую целочисленную арифметику для безопасного умножения. Несмотря на эти инженерные различия, математический алгоритм у всех трёх версий одинаков.

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

Одно вычисление \(S(N)\) занимает \(O(\sqrt N)\) времени: прямая часть проходит до \(\lfloor\sqrt N\rfloor\), а сгруппированная часть обрабатывает только \(O(\sqrt N)\) различных частных. Итоговая формула требует два таких вычисления, для \(N\) и \(\lfloor N/4\rfloor\), поэтому асимптотика остаётся \(O(\sqrt N)\). В последовательной версии используется \(O(1)\) дополнительной памяти; в параллельных версиях сверху добавляется лишь небольшой служебный расход на управление задачами.

Примечания и ссылки

  1. Страница задачи: https://projecteuler.net/problem=596
  2. Теорема Якоби о четырёх квадратах: Wikipedia - Jacobi's four-square theorem
  3. Метод гиперболы Дирихле: Wikipedia - Dirichlet hyperbola method
  4. Функция суммы квадратов: Wikipedia - Sum of squares function
  5. Точка решётки: Wikipedia - Lattice point

ملخص المسألة

نعرّف

$$T(r)=\#\left\{(x_1,x_2,x_3,x_4)\in\mathbb Z^4: x_1^2+x_2^2+x_3^2+x_4^2\le r^2\right\}.$$

المطلوب هو عدد نقاط الشبكة الصحيحة داخل الكرة الفائقة رباعية الأبعاد ذات نصف القطر \(r\). في النسخة الفعلية من المسألة نأخذ \(r=10^8\)، ثم نعيد الجواب بترديد \(10^9+7\). العدّ المباشر لكل الرباعيات الصحيحة مستحيل عملياً، لذلك يحوّل الحل المسألة الهندسية إلى مجموع عددي يعتمد على القواسم.

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

الفكرة الأساسية هي عدّ النقاط طبقةً طبقة بحسب مربع بعدها عن الأصل.

الخطوة 1: تحويل الكرة الفائقة إلى دالة تجميع

لنضع \(N=r^2\). ولكل عدد صحيح \(n\ge 0\)، نرمز بـ \(r_4(n)\) إلى عدد الرباعيات الصحيحة التي تحقق

$$x_1^2+x_2^2+x_3^2+x_4^2=n.$$

كل نقطة صحيحة داخل الكرة الفائقة تمتلك قيمة وحيدة من هذا النوع بين \(0\) و\(N\)، ولذلك

$$T(r)=\sum_{n=0}^{N} r_4(n).$$

بهذا تختفي الهندسة من الواجهة، ويصبح المطلوب مجموعاً على أعداد التمثيلات بأربعة مربعات.

الخطوة 2: تطبيق مبرهنة ياكوبي للأربعة مربعات

عندما يكون \(n>0\)، تعطي مبرهنة ياكوبي

$$r_4(n)=8\sum_{\substack{d\mid n\\4\nmid d}} d,$$

ومعها \(r_4(0)=1\). بالتعويض نحصل على

$$T(r)=1+8\sum_{n=1}^{N}\sum_{\substack{d\mid n\\4\nmid d}} d.$$

الآن نبدّل ترتيب الجمع. إذا ثبّتْنا القاسم \(d\)، فإنه يظهر مرة واحدة لكل مضاعف له لا يتجاوز \(N\)، أي

$$\left\lfloor\frac{N}{d}\right\rfloor$$

مرات. ومن ثم

$$T(r)=1+8\sum_{\substack{d\le N\\4\nmid d}} d\left\lfloor\frac{N}{d}\right\rfloor.$$

الخطوة 3: فصل الحدود المضاعفة لـ 4

لنعرّف الدالة

$$S(N)=\sum_{d=1}^{N} d\left\lfloor\frac{N}{d}\right\rfloor.$$

الحدود غير المسموح بها هي بالضبط الحدود التي فيها \(d=4k\). مساهمتها تساوي

$$\sum_{k=1}^{\lfloor N/4\rfloor} 4k\left\lfloor\frac{N}{4k}\right\rfloor.$$

وبما أن

$$\left\lfloor\frac{N}{4k}\right\rfloor=\left\lfloor \frac{\left\lfloor N/4\right\rfloor}{k}\right\rfloor,$$

فإن هذا المجموع يساوي تماماً

$$4S\!\left(\left\lfloor\frac{N}{4}\right\rfloor\right).$$

إذن تصبح الصيغة النهائية للمسألة

$$\boxed{T(r)=1+8\left(S(N)-4S\!\left(\left\lfloor\frac{N}{4}\right\rfloor\right)\right),\qquad N=r^2.}$$

الخطوة 4: حساب \(S(N)\) بزمن \(O(\sqrt N)\)

الحساب المباشر لـ \(S(N)\) يبقى خطياً في \(N\)، وهذا ما نتجنبه. الفكرة هي أن القيمة

$$\left\lfloor\frac{N}{d}\right\rfloor$$

تتكرر على فترات طويلة.

لنضع

$$M=\left\lfloor\sqrt N\right\rfloor.$$

بالنسبة إلى القواسم الصغيرة \(1\le d\le M\)، نجمع مباشرة:

$$\sum_{d=1}^{M} d\left\lfloor\frac{N}{d}\right\rfloor.$$

أما القواسم الكبيرة \(d>M\)، فنجمّعها بحسب خارج القسمة المشترك

$$q=\left\lfloor\frac{N}{d}\right\rfloor.$$

كل القيم \(d\) التي تعطي نفس \(q\) تقع في المجال

$$L_q=\left\lfloor\frac{N}{q+1}\right\rfloor+1,\qquad R_q=\left\lfloor\frac{N}{q}\right\rfloor.$$

ولأن الجزء الثاني يجب أن يشمل فقط القواسم الأكبر من \(M\)، فإن الحد الأدنى الفعلي يصبح \(\max(M+1,L_q)\). عندها تكون مساهمة المجموعة كلها

$$q\sum_{d=\max(M+1,L_q)}^{R_q} d,$$

ويحسب المجموع الداخلي بواسطة صيغة المتتالية الحسابية

$$\sum_{d=l}^{r} d=\frac{(l+r)(r-l+1)}{2}.$$

بهذه الطريقة نمرّ على عدد يقارب \(2\sqrt N\) من المجالات المفيدة فقط، بدلاً من المرور على جميع القواسم حتى \(N\).

الخطوة 5: تنفيذ الحساب تحت الترديد \(10^9+7\)

الجواب النهائي مطلوب بترديد

$$P=10^9+7.$$

لذلك تُختزل كل عملية جمع وضرب مباشرةً بترديد \(P\). والقسمة على \(2\) في مجموع المتتالية الحسابية تُستبدل بالمعكوس الضربي

$$2^{-1}\equiv 500000004 \pmod{P}.$$

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

مثال محلول: \(r=2\)

في هذه الحالة \(N=r^2=4\). نحسب أولاً

$$S(4)=1\cdot 4+2\cdot 2+3\cdot 1+4\cdot 1=15.$$

وكذلك

$$\left\lfloor\frac{N}{4}\right\rfloor=1,\qquad S(1)=1.$$

إذن

$$T(2)=1+8(15-4\cdot 1)=1+8\cdot 11=89.$$

وهذا يطابق قيمة التحقق الصغيرة المعروفة للمسألة.

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

تعتمد تطبيقات C++ وPython وJava كلها على الصيغة نفسها:

$$T(r)=1+8\left(S(r^2)-4S\!\left(\left\lfloor\frac{r^2}{4}\right\rfloor\right)\right)\pmod{10^9+7}.$$

تبدأ كل نسخة بحساب الجذر التربيعي الصحيح لتقسيم جمع \(S(N)\) إلى قسمين. القسم الأول يجمع القواسم الصغيرة واحداً واحداً. أما القسم الثاني فيمرّ على قيم خارج القسمة \(q\)، ويعيد بناء مجال القواسم الذي يحقق هذا الخارج، ثم يقتطع منه ما يقع فوق \(\sqrt N\) فقط، وبعد ذلك يضيف مساهمة المجال دفعة واحدة بصيغة المتتالية الحسابية.

كل القيم الوسطية تبقى مختزلة بترديد \(10^9+7\). نسختا Python وJava توزعان مرحلتي الجمع على عدة عمال للاستفادة من التوازي، بينما تنفذ نسخة C++ الحساب نفسه في مسار واحد مع استخدام ضرب صحيح عريض لتأمين سلامة الضرب المعياري. ومع ذلك، فالمضمون الرياضي في اللغات الثلاث واحد تماماً.

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

حساب واحد للدالة \(S(N)\) يحتاج إلى \(O(\sqrt N)\) من الزمن، لأن الجزء المباشر يصل فقط إلى \(\lfloor\sqrt N\rfloor\)، والجزء المجمّع يمرّ على \(O(\sqrt N)\) من قيم خارج القسمة المختلفة. وبما أن الحل النهائي يحتاج إلى حساب \(S(N)\) و\(S(\lfloor N/4\rfloor)\)، فإن التعقيد الكلي يبقى \(O(\sqrt N)\). النسخة التسلسلية تستخدم \(O(1)\) من الذاكرة الإضافية، أما النسخ المتوازية فتضيف فقط كلفة إدارية بسيطة لإدارة المهام.

حواشٍ ومراجع

  1. صفحة المسألة: https://projecteuler.net/problem=596
  2. مبرهنة ياكوبي للأربعة مربعات: Wikipedia - Jacobi's four-square theorem
  3. طريقة القطع الزائد لديريشليه: Wikipedia - Dirichlet hyperbola method
  4. دالة مجموع المربعات: Wikipedia - Sum of squares function
  5. نقطة شبكية: Wikipedia - Lattice point