Define
$$T(a,n)=\left\lfloor\left(\lceil\sqrt{a}\rceil+\sqrt{a}\right)^n\right\rfloor,\qquad M=999999937.$$
The task is to evaluate
$$S(N)=\sum_{a=1}^{N} T(a,a^2)\pmod{M}$$
for \(N=5{,}000{,}000\). The exponent is already quadratic in \(a\), so direct floating-point evaluation is completely impractical; the solution instead converts the irrational power into an exact integer recurrence that can be computed modulo \(M\).
The core observation is that the expression becomes easy once we pair it with its algebraic conjugate.
For a fixed integer \(a\), let
$$m=\lceil\sqrt{a}\rceil,\qquad \alpha=m+\sqrt{a},\qquad \beta=m-\sqrt{a}.$$
Then \(\alpha\) and \(\beta\) are conjugates, and they satisfy
$$\alpha+\beta=2m,\qquad \alpha\beta=m^2-a.$$
These two symmetric quantities are integers, which is what makes the later recurrence integral.
If \(a\) is not a perfect square, then \(m-1<\sqrt{a}<m\), so
$$0<\beta=m-\sqrt{a}<1.$$
For every positive \(n\), this gives
$$0<\beta^n<1.$$
Now define
$$U_n=\alpha^n+\beta^n.$$
Since \(U_n-\alpha^n=\beta^n\) lies strictly between \(0\) and \(1\), we obtain
$$\left\lfloor\alpha^n\right\rfloor=U_n-1\qquad\text{for non-square }a.$$
If \(a\) is a perfect square, then \(m=\sqrt{a}\) and \(\beta=0\), so instead
$$\left\lfloor\alpha^n\right\rfloor=U_n=(2m)^n.$$
Therefore the entire problem reduces to computing \(U_n\) efficiently.
The numbers \(\alpha\) and \(\beta\) are the two roots of
$$x^2-2mx+(m^2-a)=0.$$
Therefore the sequence \(U_n=\alpha^n+\beta^n\) satisfies the standard second-order linear recurrence
$$U_0=2,\qquad U_1=2m,$$
$$U_n=2m\,U_{n-1}-(m^2-a)\,U_{n-2}\qquad(n\ge 2).$$
Because the coefficients and initial values are integers, every \(U_n\) is an integer. This is the exact quantity hidden behind the irrational-looking power.
Instead of iterating the recurrence all the way up to \(n=a^2\), the implementation exponentiates the base element \(m+\sqrt{a}\) directly. Represent
$$x+y\sqrt{a}$$
by the pair \((x,y)\). Then multiplication becomes
$$\left(x_1,y_1\right)\left(x_2,y_2\right)=\left(x_1x_2+a y_1y_2,\ x_1y_2+x_2y_1\right).$$
If
$$\alpha^n=X_n+Y_n\sqrt{a},$$
then its conjugate is
$$\beta^n=X_n-Y_n\sqrt{a},$$
so
$$U_n=\alpha^n+\beta^n=2X_n.$$
Binary exponentiation computes \(X_n\) in \(O(\log n)\) ring multiplications, which is essential because \(n=a^2\) can be enormous.
For each \(a\), the contribution is
$$T(a,a^2)=\begin{cases} U_{a^2}-1, & \text{if } a \text{ is not a perfect square},\\ U_{a^2}, & \text{if } a \text{ is a perfect square}. \end{cases}$$
Hence
$$S(N)=\sum_{a=1}^{N} T(a,a^2)\pmod{M}.$$
The only case distinction is whether \(a\) is square; the same ring exponentiation handles both branches.
Here \(m=\lceil\sqrt{5}\rceil=3\), so
$$\alpha=3+\sqrt{5},\qquad \beta=3-\sqrt{5},\qquad \alpha\beta=4.$$
The recurrence becomes
$$U_0=2,\qquad U_1=6,\qquad U_n=6U_{n-1}-4U_{n-2}.$$
Then
$$U_2=6\cdot 6-4\cdot 2=28,$$
so
$$T(5,2)=\left\lfloor(3+\sqrt{5})^2\right\rfloor=28-1=27.$$
Continuing,
$$U_3=144,\qquad U_4=752,\qquad U_5=3936,$$
and since \(0<\beta<1\),
$$T(5,5)=3936-1=3935.$$
This is exactly the kind of identity the implementations use, but computed modulo \(M\) and at much larger exponents.
The C++, Python, and Java implementations all follow the same plan. They scan \(a\) over a contiguous range, keep track of the current value of \(\lceil\sqrt{a}\rceil\), and update it only when \(a\) crosses a perfect square. For each \(a\), they set \(n=a^2\), exponentiate \(m+\sqrt{a}\) by binary exponentiation in the pair representation above, double the real component to recover \(U_n\), subtract \(1\) when \(a\) is not square, and add the result into a running modular sum.
To speed up the full computation, the interval \([1,N]\) is partitioned into independent chunks. Each worker computes its own partial sum modulo \(M\), and the partial results are combined at the end. The mathematics is identical in all three languages; only the concurrency mechanism differs.
For one value of \(a\), the cost is \(O(\log(a^2))=O(\log a)\) pair multiplications. Summing over all \(1\le a\le N\) gives
$$\sum_{a=1}^{N} O(\log a)=O(N\log N).$$
The working memory inside one worker is \(O(1)\). With parallel execution, total auxiliary memory is linear in the number of workers, but still constant per worker range.
Definiere
$$T(a,n)=\left\lfloor\left(\lceil\sqrt{a}\rceil+\sqrt{a}\right)^n\right\rfloor,\qquad M=999999937.$$
Gesucht ist
$$S(N)=\sum_{a=1}^{N} T(a,a^2)\pmod{M}$$
für \(N=5{,}000{,}000\). Weil der Exponent bereits quadratisch in \(a\) wächst, ist direkte Fließkomma-Auswertung unbrauchbar. Die Lösung ersetzt den irrationalen Ausdruck durch eine exakte ganzzahlige Rekursion, die nur modulo \(M\) berechnet werden muss.
Der entscheidende Schritt besteht darin, den Ausdruck zusammen mit seinem algebraischen Konjugierten zu betrachten.
Für ein festes \(a\) setze
$$m=\lceil\sqrt{a}\rceil,\qquad \alpha=m+\sqrt{a},\qquad \beta=m-\sqrt{a}.$$
Dann gilt
$$\alpha+\beta=2m,\qquad \alpha\beta=m^2-a.$$
Beides sind ganze Zahlen. Genau diese Symmetrie macht die spätere Folge ganzzahlig.
Ist \(a\) kein Quadrat, dann liegt \(\sqrt{a}\) strikt zwischen \(m-1\) und \(m\), also
$$0<\beta=m-\sqrt{a}<1.$$
Somit gilt für jedes positive \(n\)
$$0<\beta^n<1.$$
Definiert man nun
$$U_n=\alpha^n+\beta^n,$$
dann unterscheidet sich \(U_n\) von \(\alpha^n\) nur um den kleinen positiven Rest \(\beta^n\). Daher
$$\left\lfloor\alpha^n\right\rfloor=U_n-1\qquad\text{für nichtquadratische }a.$$
Ist \(a\) dagegen ein Quadrat, so ist \(m=\sqrt{a}\) und damit \(\beta=0\). Dann folgt
$$\left\lfloor\alpha^n\right\rfloor=U_n=(2m)^n.$$
Damit reduziert sich das Problem vollständig auf die effiziente Berechnung von \(U_n\).
\(\alpha\) und \(\beta\) sind die beiden Nullstellen von
$$x^2-2mx+(m^2-a)=0.$$
Daher erfüllt die Folge \(U_n=\alpha^n+\beta^n\) die lineare Rekursion zweiter Ordnung
$$U_0=2,\qquad U_1=2m,$$
$$U_n=2m\,U_{n-1}-(m^2-a)\,U_{n-2}\qquad(n\ge 2).$$
Die Koeffizienten und Startwerte sind ganzzahlig, also ist jedes \(U_n\) ebenfalls ganzzahlig.
Statt die Rekursion bis \(n=a^2\) auszuwerten, potenziert die Implementierung direkt das Basiselement \(m+\sqrt{a}\). Schreibe
$$x+y\sqrt{a}$$
als Paar \((x,y)\). Dann lautet die Multiplikation
$$\left(x_1,y_1\right)\left(x_2,y_2\right)=\left(x_1x_2+a y_1y_2,\ x_1y_2+x_2y_1\right).$$
Wenn
$$\alpha^n=X_n+Y_n\sqrt{a},$$
dann ist das Konjugierte
$$\beta^n=X_n-Y_n\sqrt{a},$$
und folglich
$$U_n=2X_n.$$
Mit binärer Exponentiation gelingt dies in \(O(\log n)\) Ringmultiplikationen.
Für jedes \(a\) ist der Beitrag
$$T(a,a^2)=\begin{cases} U_{a^2}-1, & \text{falls } a \text{ kein Quadrat ist},\\ U_{a^2}, & \text{falls } a \text{ ein Quadrat ist}. \end{cases}$$
Also
$$S(N)=\sum_{a=1}^{N} T(a,a^2)\pmod{M}.$$
Die einzige Fallunterscheidung ist also die Frage, ob \(a\) ein Quadrat ist; der eigentliche Potenzierungsmechanismus bleibt derselbe.
Hier ist \(m=\lceil\sqrt{5}\rceil=3\). Damit
$$\alpha=3+\sqrt{5},\qquad \beta=3-\sqrt{5},\qquad \alpha\beta=4.$$
Die Rekursion lautet
$$U_0=2,\qquad U_1=6,\qquad U_n=6U_{n-1}-4U_{n-2}.$$
Daraus folgt
$$U_2=6\cdot 6-4\cdot 2=28,$$
also
$$T(5,2)=\left\lfloor(3+\sqrt{5})^2\right\rfloor=28-1=27.$$
Weiter erhält man
$$U_3=144,\qquad U_4=752,\qquad U_5=3936,$$
und wegen \(0<\beta<1\)
$$T(5,5)=3936-1=3935.$$
Genau dieses Prinzip verwenden die Implementierungen, nur modulo \(M\) und für sehr große Exponenten.
Die C++-, Python- und Java-Implementierungen benutzen denselben mathematischen Kern. Sie durchlaufen \(a\) auf zusammenhängenden Intervallen, halten das aktuelle \(\lceil\sqrt{a}\rceil\) fest und aktualisieren es nur dann, wenn \(a\) ein neues Quadrat erreicht. Für jedes \(a\) setzen sie \(n=a^2\), potenzieren \(m+\sqrt{a}\) mit binärer Exponentiation in der Paar-Darstellung, verdoppeln die reelle Komponente zu \(U_n\), ziehen bei Nicht-Quadraten \(1\) ab und addieren den Beitrag modulo \(M\).
Für die Gesamtrechnung wird \([1,N]\) in unabhängige Teilbereiche zerlegt. Jeder Worker berechnet seine partielle Summe modulo \(M\); am Ende werden nur noch diese partiellen Ergebnisse zusammengeführt. Die mathematische Idee ist in allen drei Sprachen identisch, unterschiedlich ist nur die jeweilige Parallelisierung.
Für ein einzelnes \(a\) benötigt die Methode \(O(\log(a^2))=O(\log a)\) Paarmultiplikationen. Insgesamt ergibt sich daher
$$\sum_{a=1}^{N} O(\log a)=O(N\log N).$$
Der zusätzliche Speicher innerhalb eines Workers ist \(O(1)\). Bei paralleler Ausführung wächst der Gesamtspeicher nur mit der Anzahl der Worker, bleibt aber pro Teilbereich konstant.
Şunu tanımlayalım:
$$T(a,n)=\left\lfloor\left(\lceil\sqrt{a}\rceil+\sqrt{a}\right)^n\right\rfloor,\qquad M=999999937.$$
İstenen değer
$$S(N)=\sum_{a=1}^{N} T(a,a^2)\pmod{M}$$
olup burada \(N=5{,}000{,}000\) alınır. Üs zaten \(a^2\) kadar büyüdüğü için doğrudan kayan noktalı hesap yapmak mümkün değildir. Çözüm, irrasyonel ifadeyi tam sayılı bir yinelemeye dönüştürür ve her şeyi yalnızca modulo \(M\) altında hesaplar.
Ana fikir, ifadenin kendisini cebirsel eşleniğiyle birlikte ele almaktır.
Sabit bir \(a\) için
$$m=\lceil\sqrt{a}\rceil,\qquad \alpha=m+\sqrt{a},\qquad \beta=m-\sqrt{a}$$
olsun. Bu durumda
$$\alpha+\beta=2m,\qquad \alpha\beta=m^2-a$$
elde edilir. Bu iki simetrik ifade tam sayıdır; birazdan kurulacak yinelemenin tam sayılı olmasının sebebi de budur.
Eğer \(a\) tam kare değilse, \(\sqrt{a}\) sayısı \(m-1\) ile \(m\) arasındadır. Dolayısıyla
$$0<\beta=m-\sqrt{a}<1.$$
Böylece her pozitif \(n\) için
$$0<\beta^n<1$$
olur. Şimdi
$$U_n=\alpha^n+\beta^n$$
tanımını yapalım. O zaman \(U_n\), \(\alpha^n\)'den yalnızca \(0\) ile \(1\) arasındaki küçük \(\beta^n\) kadar büyüktür. Bu yüzden
$$\left\lfloor\alpha^n\right\rfloor=U_n-1\qquad\text{tam kare olmayan }a\text{ için}.$$
Eğer \(a\) tam kareyse \(m=\sqrt{a}\) ve \(\beta=0\) olur. Bu özel durumda
$$\left\lfloor\alpha^n\right\rfloor=U_n=(2m)^n.$$
Yani problem tamamen \(U_n\)'yi hızlı hesaplama problemine indirgenir.
\(\alpha\) ve \(\beta\),
$$x^2-2mx+(m^2-a)=0$$
denkleminin iki köküdür. Bu yüzden \(U_n=\alpha^n+\beta^n\) dizisi
$$U_0=2,\qquad U_1=2m,$$
$$U_n=2m\,U_{n-1}-(m^2-a)\,U_{n-2}\qquad(n\ge 2)$$
yinelemesini sağlar. Katsayılar ve başlangıç değerleri tam sayı olduğu için her \(U_n\) de tam sayıdır.
\(n=a^2\) çok büyük olabildiğinden, yinelemeyi tek tek ilerletmek yerine taban elemanı \(m+\sqrt{a}\) doğrudan üsse yükseltilir. Şu gösterimi kullanalım:
$$x+y\sqrt{a}\longleftrightarrow (x,y).$$
O zaman çarpım kuralı
$$\left(x_1,y_1\right)\left(x_2,y_2\right)=\left(x_1x_2+a y_1y_2,\ x_1y_2+x_2y_1\right)$$
şeklindedir. Eğer
$$\alpha^n=X_n+Y_n\sqrt{a}$$
ise eşlenik kuvvet
$$\beta^n=X_n-Y_n\sqrt{a}$$
olur; dolayısıyla
$$U_n=\alpha^n+\beta^n=2X_n.$$
İkili üs alma sayesinde bu hesap \(O(\log n)\) halka çarpımıyla biter.
Her \(a\) için katkı
$$T(a,a^2)=\begin{cases} U_{a^2}-1, & \text{eğer } a \text{ tam kare değilse},\\ U_{a^2}, & \text{eğer } a \text{ tam kareyse}. \end{cases}$$
Bu nedenle
$$S(N)=\sum_{a=1}^{N} T(a,a^2)\pmod{M}$$
olur. Tek ayrım \(a\)'nın tam kare olup olmadığıdır; esas üs alma yöntemi iki durumda da aynıdır.
Burada \(m=\lceil\sqrt{5}\rceil=3\) olduğundan
$$\alpha=3+\sqrt{5},\qquad \beta=3-\sqrt{5},\qquad \alpha\beta=4.$$
Yineleme
$$U_0=2,\qquad U_1=6,\qquad U_n=6U_{n-1}-4U_{n-2}$$
şeklini alır. Böylece
$$U_2=6\cdot 6-4\cdot 2=28,$$
ve dolayısıyla
$$T(5,2)=\left\lfloor(3+\sqrt{5})^2\right\rfloor=28-1=27.$$
Devam edersek
$$U_3=144,\qquad U_4=752,\qquad U_5=3936,$$
olur. \(0<\beta<1\) olduğu için
$$T(5,5)=3936-1=3935.$$
Uygulamalar tam olarak bu özdeşliği kullanır; fark sadece hesapların modulo \(M\) altında ve çok daha büyük üslerde yapılmasıdır.
C++, Python ve Java uygulamaları aynı matematiksel planı izler. \(a\) değerleri bitişik aralıklara bölünür; her aralıkta mevcut \(\lceil\sqrt{a}\rceil\) değeri tutulur ve yalnızca \(a\) yeni bir kareyi geçtiğinde güncellenir. Her \(a\) için önce \(n=a^2\) alınır, ardından \(m+\sqrt{a}\) yukarıdaki çift gösterimiyle ikili üs alma kullanılarak hesaplanır, reel kısım ikiyle çarpılıp \(U_n\) elde edilir, \(a\) tam kare değilse \(1\) çıkarılır ve sonuç modüler toplamın içine eklenir.
Tam çözümü hızlandırmak için \([1,N]\) aralığı bağımsız parçalara ayrılır. Her işçi kendi parçasının toplamını modulo \(M\) hesaplar; sonunda bu kısmi toplamlar birleştirilir. Üç dilde de matematik aynıdır, değişen yalnızca paralel yürütme biçimidir.
Tek bir \(a\) için maliyet \(O(\log(a^2))=O(\log a)\) halka çarpımıdır. Tüm aralık üzerinde toplam maliyet
$$\sum_{a=1}^{N} O(\log a)=O(N\log N)$$
olur. Bir işçinin kullandığı ek bellek \(O(1)\)'dir. Paralel çalışmada toplam yardımcı bellek işçi sayısıyla artar, ancak işçi başına sabit kalır.
Definimos
$$T(a,n)=\left\lfloor\left(\lceil\sqrt{a}\rceil+\sqrt{a}\right)^n\right\rfloor,\qquad M=999999937.$$
Hay que calcular
$$S(N)=\sum_{a=1}^{N} T(a,a^2)\pmod{M}$$
para \(N=5{,}000{,}000\). Como el exponente ya es cuadrático en \(a\), una evaluación directa con números reales no sirve. La solución transforma la potencia irracional en una sucesión entera exacta y luego trabaja siempre módulo \(M\).
La observación central es que la expresión se simplifica si se estudia junto con su conjugado algebraico.
Para un \(a\) fijo, sea
$$m=\lceil\sqrt{a}\rceil,\qquad \alpha=m+\sqrt{a},\qquad \beta=m-\sqrt{a}.$$
Entonces
$$\alpha+\beta=2m,\qquad \alpha\beta=m^2-a.$$
Estas dos cantidades simétricas son enteras, y esa es la razón de que aparezca una recurrencia con coeficientes enteros.
Si \(a\) no es un cuadrado perfecto, entonces \(m-1<\sqrt{a}<m\), de modo que
$$0<\beta=m-\sqrt{a}<1.$$
Por tanto, para todo \(n>0\),
$$0<\beta^n<1.$$
Definimos
$$U_n=\alpha^n+\beta^n.$$
Como \(U_n-\alpha^n=\beta^n\) está estrictamente entre \(0\) y \(1\), se deduce que
$$\left\lfloor\alpha^n\right\rfloor=U_n-1\qquad\text{cuando }a\text{ no es cuadrado}.$$
Si \(a\) sí es cuadrado perfecto, entonces \(m=\sqrt{a}\) y \(\beta=0\), así que
$$\left\lfloor\alpha^n\right\rfloor=U_n=(2m)^n.$$
Con esto, todo el problema se reduce a calcular \(U_n\) con rapidez.
\(\alpha\) y \(\beta\) son las raíces de
$$x^2-2mx+(m^2-a)=0.$$
Por ello la sucesión \(U_n=\alpha^n+\beta^n\) satisface
$$U_0=2,\qquad U_1=2m,$$
$$U_n=2m\,U_{n-1}-(m^2-a)\,U_{n-2}\qquad(n\ge 2).$$
Los coeficientes y los valores iniciales son enteros, de modo que cada \(U_n\) también lo es.
En lugar de avanzar la recurrencia hasta \(n=a^2\), la implementación eleva directamente \(m+\sqrt{a}\). Representamos
$$x+y\sqrt{a}$$
por el par \((x,y)\). Entonces la multiplicación es
$$\left(x_1,y_1\right)\left(x_2,y_2\right)=\left(x_1x_2+a y_1y_2,\ x_1y_2+x_2y_1\right).$$
Si
$$\alpha^n=X_n+Y_n\sqrt{a},$$
entonces
$$\beta^n=X_n-Y_n\sqrt{a},$$
y por consiguiente
$$U_n=2X_n.$$
La exponenciación binaria reduce el coste a \(O(\log n)\) multiplicaciones en ese anillo.
La contribución de cada \(a\) es
$$T(a,a^2)=\begin{cases} U_{a^2}-1, & \text{si } a \text{ no es cuadrado perfecto},\\ U_{a^2}, & \text{si } a \text{ es cuadrado perfecto}. \end{cases}$$
Por tanto,
$$S(N)=\sum_{a=1}^{N} T(a,a^2)\pmod{M}.$$
La única bifurcación real es decidir si \(a\) es cuadrado; el mecanismo algebraico es el mismo en ambos casos.
Aquí \(m=\lceil\sqrt{5}\rceil=3\), así que
$$\alpha=3+\sqrt{5},\qquad \beta=3-\sqrt{5},\qquad \alpha\beta=4.$$
La recurrencia queda
$$U_0=2,\qquad U_1=6,\qquad U_n=6U_{n-1}-4U_{n-2}.$$
Entonces
$$U_2=6\cdot 6-4\cdot 2=28,$$
y por ello
$$T(5,2)=\left\lfloor(3+\sqrt{5})^2\right\rfloor=28-1=27.$$
Siguiendo la recurrencia,
$$U_3=144,\qquad U_4=752,\qquad U_5=3936,$$
de modo que, como \(0<\beta<1\),
$$T(5,5)=3936-1=3935.$$
Ese es exactamente el tipo de identidad que usan las implementaciones, solo que módulo \(M\) y con exponentes muchísimo mayores.
Las implementaciones en C++, Python y Java siguen el mismo esquema. Recorren \(a\) por intervalos contiguos, mantienen el valor actual de \(\lceil\sqrt{a}\rceil\) y lo actualizan únicamente cuando \(a\) alcanza un nuevo cuadrado perfecto. Para cada \(a\), fijan \(n=a^2\), elevan \(m+\sqrt{a}\) con exponenciación binaria en la representación por pares, duplican la parte real para recuperar \(U_n\), restan \(1\) cuando \(a\) no es cuadrado y acumulan la suma módulo \(M\).
Para acelerar el cálculo completo, el intervalo \([1,N]\) se divide en bloques independientes. Cada trabajador produce una suma parcial módulo \(M\), y al final solo se combinan esas sumas. La matemática es la misma en los tres lenguajes; cambia únicamente la herramienta de paralelismo.
Para un valor de \(a\), el coste es \(O(\log(a^2))=O(\log a)\) multiplicaciones de pares. Sumando sobre todo el rango se obtiene
$$\sum_{a=1}^{N} O(\log a)=O(N\log N).$$
La memoria de trabajo dentro de un trabajador es \(O(1)\). Con ejecución paralela, la memoria auxiliar total crece con el número de trabajadores, pero sigue siendo constante por bloque.
定义
$$T(a,n)=\left\lfloor\left(\lceil\sqrt{a}\rceil+\sqrt{a}\right)^n\right\rfloor,\qquad M=999999937.$$
要求计算
$$S(N)=\sum_{a=1}^{N} T(a,a^2)\pmod{M}$$
其中 \(N=5{,}000{,}000\)。由于指数本身就是 \(a^2\),如果直接用浮点数去算无理数高次幂,不仅速度完全不够,精度也不可靠。真正可行的方法是把这个看似无理的表达式改写成一个精确的整数递推,并且全程只在模 \(M\) 意义下运算。
关键观察是:单独看 \(\left(\lceil\sqrt{a}\rceil+\sqrt{a}\right)^n\) 很难,但把它和共轭一起看,结构就会立刻变整齐。
对固定的整数 \(a\),令
$$m=\lceil\sqrt{a}\rceil,\qquad \alpha=m+\sqrt{a},\qquad \beta=m-\sqrt{a}.$$
于是 \(\alpha\) 与 \(\beta\) 是一对共轭,并且满足
$$\alpha+\beta=2m,\qquad \alpha\beta=m^2-a.$$
这两个对称量都是整数。后面出现整数递推,根源就在这里。
如果 \(a\) 不是完全平方数,那么 \(\sqrt{a}\) 严格落在 \(m-1\) 与 \(m\) 之间,因此
$$0<\beta=m-\sqrt{a}<1.$$
于是对任意正整数 \(n\),都有
$$0<\beta^n<1.$$
现在定义
$$U_n=\alpha^n+\beta^n.$$
因为 \(U_n-\alpha^n=\beta^n\) 恰好是一个介于 \(0\) 和 \(1\) 之间的正数,所以
$$\left\lfloor\alpha^n\right\rfloor=U_n-1\qquad\text{当 }a\text{ 不是完全平方数时}.$$
如果 \(a\) 是完全平方数,那么 \(m=\sqrt{a}\),此时 \(\beta=0\),于是
$$\left\lfloor\alpha^n\right\rfloor=U_n=(2m)^n.$$
也就是说,原题实际上等价于快速求出 \(U_n\)。
\(\alpha\) 与 \(\beta\) 正好是二次方程
$$x^2-2mx+(m^2-a)=0$$
的两个根。因此序列 \(U_n=\alpha^n+\beta^n\) 满足标准的二阶线性递推:
$$U_0=2,\qquad U_1=2m,$$
$$U_n=2m\,U_{n-1}-(m^2-a)\,U_{n-2}\qquad(n\ge 2).$$
由于系数和初值都是整数,所以每一个 \(U_n\) 都是整数。这一步把“无理数高次幂”彻底转化成了“整数序列”。
虽然递推是正确的,但若真的从 \(U_0\) 一直推到 \(U_{a^2}\),代价仍然太高,因为指数是 \(a^2\)。实现采用更快的办法:直接对元素 \(m+\sqrt{a}\) 做二进制快速幂。把
$$x+y\sqrt{a}$$
表示成一对数 \((x,y)\)。那么乘法规则就是
$$\left(x_1,y_1\right)\left(x_2,y_2\right)=\left(x_1x_2+a y_1y_2,\ x_1y_2+x_2y_1\right).$$
若
$$\alpha^n=X_n+Y_n\sqrt{a},$$
则共轭幂自然为
$$\beta^n=X_n-Y_n\sqrt{a},$$
相加后立刻得到
$$U_n=\alpha^n+\beta^n=2X_n.$$
因此只要用快速幂求出 \(\alpha^n\) 的实部,就能在 \(O(\log n)\) 次配对乘法内得到 \(U_n\)。这正是程序在模 \(M\) 下执行的核心操作。
对每个 \(a\),对应项为
$$T(a,a^2)=\begin{cases} U_{a^2}-1, & \text{如果 } a \text{ 不是完全平方数},\\ U_{a^2}, & \text{如果 } a \text{ 是完全平方数}. \end{cases}$$
因此总和就是
$$S(N)=\sum_{a=1}^{N} T(a,a^2)\pmod{M}.$$
整个算法的唯一分支只有“\(a\) 是否为完全平方数”这一点;其余计算流程完全一致。
当 \(a=5\) 时,\(m=\lceil\sqrt{5}\rceil=3\),所以
$$\alpha=3+\sqrt{5},\qquad \beta=3-\sqrt{5},\qquad \alpha\beta=4.$$
递推变成
$$U_0=2,\qquad U_1=6,\qquad U_n=6U_{n-1}-4U_{n-2}.$$
先算前几项:
$$U_2=6\cdot 6-4\cdot 2=28.$$
由于 \(a=5\) 不是完全平方数,故
$$T(5,2)=\left\lfloor(3+\sqrt{5})^2\right\rfloor=28-1=27.$$
继续递推可得
$$U_3=144,\qquad U_4=752,\qquad U_5=3936.$$
因为始终有 \(0<\beta<1\),所以
$$T(5,5)=3936-1=3935.$$
程序对每个 \(a\) 做的事情,本质上就是这套推导,只不过指数换成了 \(a^2\),并且所有运算都搬到了模 \(M\) 的世界里。
C++、Python 和 Java 三个实现采用完全相同的数学方案。它们把 \(a\) 的取值区间划分成若干连续块,在每个块内维护当前的 \(\lceil\sqrt{a}\rceil\) 以及对应平方,只在跨过新的平方数时才更新。对每个 \(a\),先令 \(n=a^2\),再用上面的配对表示对 \(m+\sqrt{a}\) 做二进制快速幂,取结果实部的两倍得到 \(U_n\),若 \(a\) 不是完全平方数则再减去 \(1\),最后累加到模 \(M\) 的部分和中。
为了加速总计算,区间 \([1,N]\) 被拆成互不依赖的子区间。每个工作单元独立算出自己的模 \(M\) 部分和,最后再把这些部分和合并。三种语言的差别只在并行工具的写法上,数学流程并没有变化。
对单个 \(a\),快速幂需要 \(O(\log(a^2))=O(\log a)\) 次配对乘法。于是总时间复杂度为
$$\sum_{a=1}^{N} O(\log a)=O(N\log N).$$
单个工作单元的额外空间是 \(O(1)\)。若采用并行执行,总辅助空间会随工作单元数量线性增长,但对每个子区间来说仍是常数级。
Определим
$$T(a,n)=\left\lfloor\left(\lceil\sqrt{a}\rceil+\sqrt{a}\right)^n\right\rfloor,\qquad M=999999937.$$
Нужно вычислить
$$S(N)=\sum_{a=1}^{N} T(a,a^2)\pmod{M}$$
при \(N=5{,}000{,}000\). Поскольку показатель степени равен \(a^2\), прямое вычисление иррациональной степени с плавающей точкой здесь бесполезно. Решение переводит задачу в точную целочисленную рекурсию и затем работает только по модулю \(M\).
Главная идея состоит в том, чтобы рассматривать выражение вместе с его алгебраическим сопряжением.
Для фиксированного \(a\) положим
$$m=\lceil\sqrt{a}\rceil,\qquad \alpha=m+\sqrt{a},\qquad \beta=m-\sqrt{a}.$$
Тогда
$$\alpha+\beta=2m,\qquad \alpha\beta=m^2-a.$$
Обе симметрические величины целые, и именно поэтому в дальнейшем возникает целочисленная рекуррентная формула.
Если \(a\) не является полным квадратом, то \(m-1<\sqrt{a}<m\), следовательно
$$0<\beta=m-\sqrt{a}<1.$$
Значит, для любого положительного \(n\)
$$0<\beta^n<1.$$
Определим
$$U_n=\alpha^n+\beta^n.$$
Так как \(U_n-\alpha^n=\beta^n\) строго между \(0\) и \(1\), получаем
$$\left\lfloor\alpha^n\right\rfloor=U_n-1\qquad\text{для неквадратных }a.$$
Если же \(a\) является полным квадратом, то \(m=\sqrt{a}\) и \(\beta=0\), поэтому
$$\left\lfloor\alpha^n\right\rfloor=U_n=(2m)^n.$$
Итак, задача сводится к быстрому вычислению \(U_n\).
\(\alpha\) и \(\beta\) являются корнями уравнения
$$x^2-2mx+(m^2-a)=0.$$
Отсюда последовательность \(U_n=\alpha^n+\beta^n\) удовлетворяет рекурсии
$$U_0=2,\qquad U_1=2m,$$
$$U_n=2m\,U_{n-1}-(m^2-a)\,U_{n-2}\qquad(n\ge 2).$$
Поскольку коэффициенты и начальные значения целые, каждое \(U_n\) тоже целое.
Идти по рекурсии до \(n=a^2\) слишком дорого, поэтому реализация напрямую возводит в степень элемент \(m+\sqrt{a}\). Представим
$$x+y\sqrt{a}$$
в виде пары \((x,y)\). Тогда правило умножения таково:
$$\left(x_1,y_1\right)\left(x_2,y_2\right)=\left(x_1x_2+a y_1y_2,\ x_1y_2+x_2y_1\right).$$
Если
$$\alpha^n=X_n+Y_n\sqrt{a},$$
то
$$\beta^n=X_n-Y_n\sqrt{a},$$
и значит
$$U_n=2X_n.$$
Бинарное возведение в степень даёт этот результат за \(O(\log n)\) умножений пар.
Вклад каждого \(a\) равен
$$T(a,a^2)=\begin{cases} U_{a^2}-1, & \text{если } a \text{ не является полным квадратом},\\ U_{a^2}, & \text{если } a \text{ является полным квадратом}. \end{cases}$$
Следовательно,
$$S(N)=\sum_{a=1}^{N} T(a,a^2)\pmod{M}.$$
Единственное ветвление в алгоритме связано с проверкой, является ли \(a\) квадратом; сама алгебраическая схема в обоих случаях одинакова.
Здесь \(m=\lceil\sqrt{5}\rceil=3\), поэтому
$$\alpha=3+\sqrt{5},\qquad \beta=3-\sqrt{5},\qquad \alpha\beta=4.$$
Рекурсия принимает вид
$$U_0=2,\qquad U_1=6,\qquad U_n=6U_{n-1}-4U_{n-2}.$$
Тогда
$$U_2=6\cdot 6-4\cdot 2=28,$$
откуда
$$T(5,2)=\left\lfloor(3+\sqrt{5})^2\right\rfloor=28-1=27.$$
Далее получаем
$$U_3=144,\qquad U_4=752,\qquad U_5=3936,$$
и поскольку \(0<\beta<1\),
$$T(5,5)=3936-1=3935.$$
Именно эту идею используют реализации, только по модулю \(M\) и для значительно больших показателей.
Реализации на C++, Python и Java используют один и тот же математический алгоритм. Они проходят значения \(a\) по непрерывным диапазонам, хранят текущее значение \(\lceil\sqrt{a}\rceil\) и обновляют его только тогда, когда \(a\) достигает следующего квадрата. Для каждого \(a\) берётся \(n=a^2\), затем элемент \(m+\sqrt{a}\) возводится в степень бинарным методом в парном представлении, действительная часть удваивается, чтобы получить \(U_n\), для неквадратных \(a\) вычитается \(1\), и результат добавляется к модульной сумме.
Чтобы ускорить полный расчёт, интервал \([1,N]\) делится на независимые куски. Каждый рабочий поток или процесс считает свою частичную сумму по модулю \(M\), а затем все частичные суммы объединяются. Математика во всех трёх языках одинакова; различается только механизм параллельного выполнения.
Для одного значения \(a\) стоимость равна \(O(\log(a^2))=O(\log a)\) умножений пар. Поэтому суммарная сложность равна
$$\sum_{a=1}^{N} O(\log a)=O(N\log N).$$
Дополнительная память внутри одного рабочего блока равна \(O(1)\). При параллельном запуске суммарная вспомогательная память растёт вместе с числом рабочих блоков, но на один блок остаётся постоянной.
نعرّف
$$T(a,n)=\left\lfloor\left(\lceil\sqrt{a}\rceil+\sqrt{a}\right)^n\right\rfloor,\qquad M=999999937.$$
والمطلوب هو حساب
$$S(N)=\sum_{a=1}^{N} T(a,a^2)\pmod{M}$$
عند \(N=5{,}000{,}000\). بما أن الأس يساوي \(a^2\)، فالحساب المباشر باستعمال الأعداد العائمة غير عملي تمامًا. الحل الفعلي يحول هذه القوة غير النسبية إلى متتالية صحيحة دقيقة، ثم ينفذ كل شيء تحت الحساب بترديد \(M\).
الفكرة الأساسية هي النظر إلى التعبير مع مرافقه الجبري بدلًا من النظر إليه منفردًا.
لكل عدد صحيح ثابت \(a\)، نضع
$$m=\lceil\sqrt{a}\rceil,\qquad \alpha=m+\sqrt{a},\qquad \beta=m-\sqrt{a}.$$
عندئذٍ
$$\alpha+\beta=2m,\qquad \alpha\beta=m^2-a.$$
وهاتان الكميتان متناظرتان وصحيحتان، ومن هنا تظهر العلاقة التكرارية الصحيحة لاحقًا.
إذا لم يكن \(a\) مربعًا كاملًا، فإن \(\sqrt{a}\) يقع strictly بين \(m-1\) و\(m\)، ولذلك
$$0<\beta=m-\sqrt{a}<1.$$
ومن ثم لكل \(n>0\)
$$0<\beta^n<1.$$
نعرّف الآن
$$U_n=\alpha^n+\beta^n.$$
وبما أن الفرق \(U_n-\alpha^n=\beta^n\) يقع بدقة بين \(0\) و\(1\)، نحصل في حالة \(a\) غير المربع الكامل على
$$\left\lfloor\alpha^n\right\rfloor=U_n-1.$$
أما إذا كان \(a\) مربعًا كاملًا، فإن \(m=\sqrt{a}\) وبالتالي \(\beta=0\)، وعندها
$$\left\lfloor\alpha^n\right\rfloor=U_n=(2m)^n.$$
إذن المشكلة تختزل بالكامل إلى حساب \(U_n\) بسرعة.
إن \(\alpha\) و\(\beta\) هما جذرا المعادلة
$$x^2-2mx+(m^2-a)=0.$$
ولذلك فإن المتتالية \(U_n=\alpha^n+\beta^n\) تحقق
$$U_0=2,\qquad U_1=2m,$$
$$U_n=2m\,U_{n-1}-(m^2-a)\,U_{n-2}\qquad(n\ge 2).$$
وبما أن المعاملات والقيم الابتدائية كلها أعداد صحيحة، فإن كل \(U_n\) يكون عددًا صحيحًا أيضًا.
لا يمكن دفع العلاقة التكرارية خطوة خطوة حتى \(n=a^2\)، لذلك تنفذ التطبيقات رفع \(m+\sqrt{a}\) مباشرةً باستعمال الأس الثنائي. نمثل
$$x+y\sqrt{a}$$
بالزوج \((x,y)\). وعندئذ تصبح قاعدة الضرب
$$\left(x_1,y_1\right)\left(x_2,y_2\right)=\left(x_1x_2+a y_1y_2,\ x_1y_2+x_2y_1\right).$$
إذا كان
$$\alpha^n=X_n+Y_n\sqrt{a},$$
فإن
$$\beta^n=X_n-Y_n\sqrt{a},$$
ومن ثم
$$U_n=2X_n.$$
وهكذا يمكن الحصول على \(U_n\) في \(O(\log n)\) من ضرب الأزواج، وهو ما يجعل الحساب ممكنًا.
مساهمة كل قيمة \(a\) تأخذ شكلين بسيطين. إذا لم يكن \(a\) مربعًا كاملًا، فلدينا
$$T(a,a^2)=U_{a^2}-1.$$
أما إذا كان \(a\) مربعًا كاملًا، فلدينا
$$T(a,a^2)=U_{a^2}.$$
إذن
$$S(N)=\sum_{a=1}^{N} T(a,a^2)\pmod{M}.$$
ولا توجد أي حالة خاصة أخرى غير التحقق من كون \(a\) مربعًا كاملًا.
لدينا هنا \(m=\lceil\sqrt{5}\rceil=3\)، وبالتالي
$$\alpha=3+\sqrt{5},\qquad \beta=3-\sqrt{5},\qquad \alpha\beta=4.$$
تصبح العلاقة التكرارية
$$U_0=2,\qquad U_1=6,\qquad U_n=6U_{n-1}-4U_{n-2}.$$
ومنها
$$U_2=6\cdot 6-4\cdot 2=28,$$
لذلك
$$T(5,2)=\left\lfloor(3+\sqrt{5})^2\right\rfloor=28-1=27.$$
وبالاستمرار نحصل على
$$U_3=144,\qquad U_4=752,\qquad U_5=3936,$$
ومع \(0<\beta<1\) ينتج
$$T(5,5)=3936-1=3935.$$
هذا بالضبط هو المبدأ الذي تعتمد عليه التطبيقات، لكن تحت الترديد \(M\) ومع أسس أكبر بكثير.
تتبع تطبيقات C++ وPython وJava الخطة الرياضية نفسها. فهي تقسم المجال \([1,N]\) إلى مقاطع متجاورة، وتحافظ داخل كل مقطع على القيمة الحالية لـ \(\lceil\sqrt{a}\rceil\) وتحدثها فقط عندما يتجاوز \(a\) مربعًا كاملًا جديدًا. لكل \(a\) يتم تعيين \(n=a^2\)، ثم يُرفع العنصر \(m+\sqrt{a}\) بالأس الثنائي في تمثيل الأزواج، وتُضاعف الجهة الحقيقية لاستخراج \(U_n\)، ثم يُطرح \(1\) إذا لم يكن \(a\) مربعًا كاملًا، وبعد ذلك تُضاف النتيجة إلى مجموع جزئي بترديد \(M\).
ولتسريع الحساب الكلي، تُعالج المقاطع بشكل مستقل. كل عامل يحسب مجموعه الجزئي modulo \(M\)، ثم تُجمع هذه المجاميع في النهاية. الاختلاف بين اللغات الثلاث موجود في وسيلة التنفيذ المتوازي فقط، أما الجوهر الرياضي فواحد.
لكل قيمة \(a\)، نحتاج إلى \(O(\log(a^2))=O(\log a)\) من ضرب الأزواج. ومن ثم يكون التعقيد الكلي
$$\sum_{a=1}^{N} O(\log a)=O(N\log N).$$
الذاكرة الإضافية داخل كل عامل هي \(O(1)\). ومع التنفيذ المتوازي تزداد الذاكرة المساعدة الكلية مع عدد العمال، لكنها تبقى ثابتة لكل مقطع.