Editorial for La tina de Karel
Submitting an official solution before solving the problem yourself is a bannable offence.
Author:
La temperatura actual de la bañera es:
\[ \frac{100X}{X+Y} \]
Si agregamos A cubetas calientes y B cubetas frías, la temperatura pasa a ser:
\[ \frac{100(X+A)}{X+Y+A+B} \]
Queremos encontrar A y B tales que:
\[ 100(X+A)=T(X+Y+A+B) \]
¿Cómo encontrar A y B?
Podemos construir la respuesta poco a poco.
En cada momento comparamos:
\[ 100(X+A) \]
con:
\[ T(X+Y+A+B) \]
Hay tres posibilidades:
- Si son iguales, encontramos la temperatura exacta.
Si el lado izquierdo es mayor, significa que la mezcla está demasiado caliente. Agregamos una cubeta fría:
\[ B++ \]
Si el lado izquierdo es menor, significa que la mezcla está demasiado fría. Agregamos una cubeta caliente:
\[ A++ \]
Esto se repite hasta obtener exactamente la temperatura T.
Casos especiales
Para T = 100, no puede existir ninguna cubeta fría.
Por eso:
- Si
Y > 0→IMPOSSIBLE. - Si ya existe agua caliente (
X > 0) →0 0. - Si
X = Y = 0, necesitamos agregar una cubeta caliente →1 0.
Para T = 0 ocurre lo contrario:
- Si
X > 0→IMPOSSIBLE. - Si ya existe agua fría (
Y > 0) →0 0. - Si
X = Y = 0, necesitamos agregar una cubeta fría →0 1.
Para 0 < T < 100, el procedimiento iterativo encuentra la primera combinación que alcanza exactamente la temperatura, por lo que obtiene el mínimo número de cubetas agregadas.
Ejemplo
Para:
X = 3
Y = 5
T = 78
Inicialmente:
\[ 100(3)=300 \]
y:
\[ 78(3+5)=624 \]
La mezcla está demasiado fría, así que agregamos agua caliente.
Después de varias iteraciones llegamos a:
\[ A=36,\qquad B=6 \]
Entonces tenemos:
\[ X+A=39 \]
y:
\[ Y+B=11 \]
La temperatura es:
\[ 100\frac{39}{39+11}=100\frac{39}{50}=78 \]
Por lo tanto:
36 6
Complejidad
El ciclo va agregando una cubeta en cada iteración.
En el peor caso, el número de iteraciones depende de la cantidad de cubetas necesarias, pero con los límites dados es suficientemente pequeño.
- Tiempo:
O(A+B) - Memoria:
O(1)
Código en C++
#include <bits/stdc++.h>
using namespace std;
void solve() {
long long x, y, t;
cin >> x >> y >> t;
long long a = 0, b = 0;
// Queremos obtener exactamente 100 grados.
if (t == 100) {
if (y > 0) {
cout << "IMPOSSIBLE\n";
return;
}
if (x > 0) {
cout << "0 0\n";
return;
}
// No hay agua. Necesitamos agregar una cubeta caliente.
cout << "1 0\n";
return;
}
// Queremos obtener exactamente 0 grados.
if (t == 0) {
if (x > 0) {
cout << "IMPOSSIBLE\n";
return;
}
if (y > 0) {
cout << "0 0\n";
return;
}
// No hay agua. Necesitamos agregar una cubeta fría.
cout << "0 1\n";
return;
}
// 0 < t < 100
while (100 * (x + a) != (x + y + a + b) * t) {
// La mezcla está demasiado caliente.
if (100 * (x + a) > (x + y + a + b) * t) {
b++;
}
// La mezcla está demasiado fría.
else {
a++;
}
}
cout << a << ' ' << b << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
while (T--) {
solve();
}
return 0;
}
Idea clave
La comparación
\[ 100(X+A)\quad\text{vs.}\quad T(X+Y+A+B) \]
nos dice directamente hacia qué lado tenemos que mover la temperatura:
demasiado caliente → agregar agua fría
demasiado fría → agregar agua caliente
exactamente T → terminar
Así, el código no necesita despejar ninguna ecuación ni utilizar double; todo se mantiene con enteros, evitando errores de precisión.
Comments