Editorial for Escaleras
Submitting an official solution before solving the problem yourself is a bannable offence.
Author:
Análisis del problema
Se parte del escalón \(0\) y en cada paso se sube 1 o 2 escalones. Se pide contar de cuántas maneras distintas (el orden importa) se llega al escalón \(n\), para varios casos de prueba.
Idea de la solución
Sea \(f(n)\) el número de maneras de llegar al escalón \(n\). El último paso para llegar a \(n\) solo pudo ser de dos tipos:
- Venir del escalón \(n-1\) con un paso de 1 escalón: hay \(f(n-1)\) maneras.
- Venir del escalón \(n-2\) con un paso de 2 escalones: hay \(f(n-2)\) maneras.
Como estos dos casos son disjuntos y cubren todas las posibilidades:
\(f(n) = f(n-1) + f(n-2)\)
con los casos base:
- \(f(0) = 1\) (ya estás en el piso, una manera: no hacer nada).
- \(f(1) = 1\) (solo un paso de 1).
Esto es la sucesión de Fibonacci desplazada: \(1, 1, 2, 3, 5, 8, ...\)
Verificación con el ejemplo
| \(n\) | \(f(n)\) |
|---|---|
| 0 | 1 |
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 5 |
Coincide con el ejemplo: \(f(1)=1\), \(f(2)=2\), \(f(4)=5\).
Sobre el tamaño de los números
Para \(n = 90\), \(f(90)\) es aproximadamente \(4.66 \times 10^{18}\), que es menor que \(2^{63}-1 \approx 9.22 \times 10^{18}\). Por lo tanto cabe en un long long (o unsigned long long) sin desbordamiento. Con \(n = 91\) todavía cabría, pero con \(n = 93\) ya no, así que el límite \(n \le 90\) está pensado para esto.
Estrategia
Se precalcula el arreglo f[0..90] una sola vez y cada consulta se responde en \(O(1)\).
Código en C++
#include <iostream>
using namespace std;
int main() {
const int MAXN = 90;
long long f[MAXN + 1];
f[0] = 1;
f[1] = 1;
for (int i = 2; i <= MAXN; i++) {
f[i] = f[i - 1] + f[i - 2];
}
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
cout << f[n] << "\n";
}
return 0;
}
Explicación del código
long long f[MAXN + 1]: arreglo con los resultados para todos los \(n\) de \(0\) a \(90\). Se usalong longporque los valores llegan a \(10^{18}\).f[0] = 1; f[1] = 1;: casos base.- El ciclo
foraplica la recurrencia \(f(i) = f(i-1) + f(i-2)\) y llena toda la tabla. - Se lee \(t\) y, por cada caso, se lee \(n\) y se imprime
f[n]directamente.
Complejidad
- Precálculo: \(O(M)\), con \(M = 90\).
- Consultas: \(O(t)\), una por caso.
- Total: \(O(M + t)\).
- Memoria: \(O(M)\).
Posibles errores comunes
| Error | Consecuencia |
|---|---|
Usar int en lugar de long long |
Desbordamiento desde \(n = 46\) aproximadamente, Wrong Answer |
| Recursión sin memorización | Time Limit Exceeded para \(n\) grandes |
| Definir mal los casos base (por ejemplo \(f(0)=0\)) | Toda la tabla queda desplazada o en cero |
| Tabla de tamaño \(90\) en vez de \(91\) | Acceso fuera de rango para \(n = 90\) |
Prueba con el ejemplo
Entrada
3
1
2
4
Salida
1
2
5
Comments