The problem is fundamentally about arranging cubes in 3D space to maximize edge sharing. When two cubes are placed adjacent to each other, they share a face, and the 4 edges around that face become internal to the structure rather than requiring separate matches.
The optimal arrangement is a rectangular prism with dimensions as close to each other as possible. Think of it like packing cubes into an a \times b \times c box. A cube-shaped arrangement (like 3 \times 3 \times 3) has minimal surface area, which means fewer exposed edges and thus fewer matches needed.
We can count matches by thinking of the arrangement as a 3D grid. If we have a \times b \times c cubes, the grid has (a+1) \times (b+1) \times (c+1) vertices. The matches are edges connecting these vertices in three directions: horizontal, vertical, and depth.
We start by finding k \approx \sqrt[3]{n}, approximately the cube root of . This gives us a baseline for dimensions that are roughly equal. Since int(n**(1/3)) can be off by one due to floating-point precision, we adjust upward if (k+1)^3 \leq n, or downward if k^3 > n, until we find the correct integer cube root.
Next, we try to fit cubes into one of three near-cubic arrangements: k \times k \times k, k \times k \times (k+1), or k \times (k+1) \times (k+1). We pick the largest arrangement that doesn't exceed cubes. This becomes our base block.
For the base block, we calculate the number of matches using the edge-counting formula:
In each direction, we count how many edges span that direction. For example, in the -direction, we have edges across, repeated (b+1) \times (c+1) times for each row and layer.
If there are leftover cubes after filling the base block, we arrange them optimally on top. We try to form a rectangle (approximately \sqrt{r} \times \sqrt{r} where is the remainder) to maintain compactness. Any remaining cubes that don't fit the rectangle are added in a line, which costs matches per cube plus to attach to the structure.
import math
n = int(input())
if n == 0:
print(0)
else:
# Find k ≈ cube root of n, adjusting for floating point precision
k = int(n**(1/3))
while (k+1)**3 <= n:
k += 1
while k**3 > n:
k -= 1
# Choose base block dimensions
# Try k×k×k, k×k×(k+1), or 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)
# Count matches for base block: edges in x, y, and z directions
result = a * (b+1) * (c+1) + b * (a+1) * (c+1) + c * (a+1) * (b+1)
# Add matches for remainder cubes if any
if rem > 0:
# Arrange remainder as an s×t rectangle
s = int(math.isqrt(rem))
if s > 0:
t = rem // s
else:
t = 0
left = rem - s * t
# Add edges for the rectangle on top of base block
result += (s+1) * (t+1) + s * (t+1) + t * (s+1)
# Add any leftover cubes in a line
if left > 0:
result += 3 * left + 2
print(result)Complexity Analysis:
Time complexity: - only arithmetic operations
Space complexity: - constant extra space