Aquí hay una versión que es trivialmente O (sqrt (N)) y evita todas las ramas de bucle interno.
Comience por generar todos los cuadrados hasta el límite, fácilmente sin multiplicaciones, luego inicialice un índice ly r.
En cada iteración calcula la suma, luego actualice los dos índices y el recuento basándose en una comparación con el valor objetivo. Esto es iteraciones sqrt (N) para generar la tabla y las iteraciones sqrt (N) máximas del bucle de búsqueda. El tiempo de ejecución estimado con un compilador razonable es de 10 ciclos de reloj por sqrt (N), por lo que para un valor de entrada máximo si 2^31 (sqrt (N) ~ = 46341) esto debería corresponder a menos de 500K ciclos de reloj o algunas décimas de un segundo:
unsigned countPairs(unsigned n)
{
unsigned sq = 0, i;
unsigned square[65536];
for (i = 0; sq <= n; i++) {
square[i] = sq;
sq += i+i+1;
}
unsigned l = 0, r = i-1, count = 0;
do {
unsigned sum = square[l] + square[r];
l += sum <= n; // Increment l if the sum is <= N
count += sum == n; // Increment the count if a match
r -= sum >= n; // Decrement r if the sum is >= N
} while (l <= r);
return count;
}
un buen compilador puede observar que los tres compara al final están todos usando los mismos operandos por lo que sólo necesita un único código de operación CMP seguido de tres operaciones condicionales movimiento diferente (CMOVcc).
Solo notando, esta ronda ya ha finalizado. – marcog
no se popularizó tanto como codejam. Acabo de enterarme de eso. –
@Senthil Probablemente algo bueno ya que la plataforma experimentó una serie de problemas. – marcog