Skip to Content

Multiplication Table

Explicación

Se nos pide hallar la mediana de los números de una tabla de multiplicar de n×nn \times n, donde nn es impar. Si f(x)f(x) representa cuántos números de la tabla de multiplicar son menores o iguales que xx, entonces la mediana tendrá al menos n2+12\frac{n^2 + 1}{2} números menores o iguales que ella. Así, queremos hallar el menor xx tal que f(x)n2+12f(x) \geq \frac{n^2 + 1}{2}.

Para hallar f(x)f(x), podemos recorrer cada fila de la tabla. Como los números de una fila son el número de columna multiplicado por el número de fila, podemos dividir xx por el número de fila para hallar cuántas columnas tienen un número menor o igual que xx. Tomar el mínimo entre la cantidad de columnas y nn nos dirá cuántos números de esa fila son menores o iguales que xx, y sumar sobre todas las filas nos dará f(x)f(x), que guardamos en la variable leq\texttt{leq}.

Usando leq\texttt{leq}, podemos hacer búsqueda binaria hasta hallar la mediana. Si leqn2+12\texttt{leq} \geq \frac{n^2 + 1}{2}, asignamos high\texttt{high} a mid\texttt{mid} porque mid\texttt{mid} funciona y es una cota superior de la respuesta. En caso contrario, asignamos low\texttt{low} a mid+1\texttt{mid} + 1 porque mid\texttt{mid} no funciona, así que los números menores que mid\texttt{mid} tampoco funcionarán.

Implementación

Complejidad temporal: O(NlogN)\mathcal{O}(N\log N)

#include <iostream> using namespace std; int main() { long long n; cin >> n; long long low = 1, high = n * n, mid, leq; // búsqueda binaria para obtener la mediana while (low < high) { mid = (low + high) / 2; leq = 0; for (int i = 1; i <= n; i++) { leq += min(n, mid / i); } if (leq >= (n * n + 1) / 2) { high = mid; } else { low = mid + 1; } } cout << high << endl; return 0; }
import java.io.*; import java.util.StringTokenizer; public class MultiplicationTable { public static void main(String[] args) { Kattio io = new Kattio(); long n = io.nextInt(); long low = 1, high = n * n, mid, leq; // búsqueda binaria para hallar la mediana while (low < high) { mid = (low + high) / 2; leq = 0; for (int i = 1; i <= n; i++) { leq += Math.min(n, mid / i); } if (leq >= (n * n + 1) / 2) { high = mid; } else { low = mid + 1; } } io.println(high); io.close(); } }
n = int(input()) low = 1 high = n**2 # búsqueda binaria para hallar la mediana while low < high: mid = (low + high) // 2 leq = 0 for i in range(0, n): leq += min(n, mid // (i + 1)) if leq >= (n**2 + 1) / 2: high = mid else: low = mid + 1 print(high)