Задача полягає в розміщенні кубиків у тривимірному просторі для максимізації спільного використання ребер. Коли два кубики розміщені поруч один з одним, вони ділять грань, і 4 ребра навколо цієї грані стають внутрішніми для структури, а не вимагають окремих сірників.
Оптимальне розміщення — це прямокутна призма з розмірами якомога ближчими один до одного. Уявіть це як упаковку кубиків у коробку a \times b \times c. Кубоподібне розміщення (наприклад, 3 \times 3 \times 3) має мінімальну площу поверхні, що означає менше відкритих ребер і, відповідно, менше необхідних сірників.
Ми можемо порахувати сірники, розглядаючи розміщення як тривимірну сітку. Якщо у нас є a \times b \times c кубиків, сітка має (a+1) \times (b+1) \times (c+1) вершин. Сірники — це ребра, що з'єднують ці вершини у трьох напрямках: горизонтальному, вертикальному та глибини.
Спочатку знаходимо k \approx \sqrt[3]{n}, приблизно кубічний корінь з . Це дає нам базову лінію для розмірів, які приблизно рівні. Оскільки int(n**(1/3)) може помилятися на одиницю через точність обчислень з плаваючою комою, ми коригуємо вгору, якщо (k+1)^3 \leq n, або вниз, якщо k^3 > n, поки не знайдемо правильний цілочисельний кубічний корінь.
Далі намагаємось вмістити кубиків в одне з трьох майже кубічних розміщень: k \times k \times k, k \times k \times (k+1) або k \times (k+1) \times (k+1). Обираємо найбільше розміщення, яке не перевищує кубиків. Це стає нашим базовим блоком.
Для базового блоку обчислюємо кількість сірників за формулою підрахунку ребер:
У кожному напрямку рахуємо, скільки ребер охоплюють цей напрямок. Наприклад, у напрямку маємо ребер, повторених (b+1) \times (c+1) разів для кожного ряду і шару.
Якщо після заповнення базового блоку залишаються кубики, розміщуємо їх оптимально зверху. Намагаємось сформувати прямокутник (приблизно \sqrt{r} \times \sqrt{r}, де — залишок) для збереження компактності. Будь-які кубики, що не вміщуються в прямокутник, додаються в лінію, що коштує сірники на кубик плюс для прикріплення до структури.
import math
n = int(input())
if n == 0:
print(0)
else:
# Знаходимо k ≈ кубічний корінь з n, коригуючи для точності обчислень
k = int(n**(1/3))
while (k+1)**3 <= n:
k += 1
while k**3 > n:
k -= 1
# Обираємо розміри базового блоку
# Пробуємо k×k×k, k×k×(k+1) або k×(k+1)×(k+1)
if n <= k * k * (k + 1):
a = k
b = k
c = k
rem = n - k**3
elif n <= k * (k+1) * (k+1):
a = k
b = k
c = k + 1
rem = n - k * k * (k + 1)
else:
a = k
b = k + 1
c = k + 1
rem = n - k * (k+1) * (k+1)
# Рахуємо сірники для базового блоку: ребра в напрямках x, y та z
result = a * (b+1) * (c+1) + b * (a+1) * (c+1) + c * (a+1) * (b+1)
# Додаємо сірники для залишкових кубиків, якщо такі є
if rem > 0:
# Розміщуємо залишок як прямокутник s×t
s = int(math.isqrt(rem))
if s > 0:
t = rem // s
else:
t = 0
left = rem - s * t
# Додаємо ребра для прямокутника зверху базового блоку
result += (s+1) * (t+1) + s * (t+1) + t * (s+1)
# Додаємо залишкові кубики в лінію
if left > 0:
result += 3 * left + 2
print(result)Аналіз складності:
Часова складність: — тільки арифметичні операції
Просторова складність: — константна додаткова пам'ять