```go
package main
import (
"fmt"
)
func main() {
var x, y, z, k int64
fmt.Scan(&x, &y, &z, &k)
// Maximum cuts along each axis
maxX := x - 1
// We need to distribute k cuts among 3 axes to maximize pieces
// pieces = (cx+1)*(cy+1)*(cz+1) where cx+cy+cz <= k
// and cx <= maxX, cy <= maxY, cz <= maxZ
// Greedy: distribute cuts optimally
// We want to maximize (a)*(b)*(c) where a = cx+1, b = cy+1, c = cz+1
// a <= x, b <= y, c <= z, (a-1)+(b-1)+(c-1) <= k
// i.e., a+b+c <= k+3
// Let's iterate over possible values of cx (cuts along x-axis)
// For given remaining cuts r = k - cx, distribute between y and z axes
// For fixed a cuts on x, remaining = k - a cuts for y and z
// maximize (b)*(c) with b <= y, c <= z, b+c <= remaining + 2
// Let total = remaining + 2, we want to maximize b*c with b <= y, c <= z, b+c <= total
// Optimal: b = min(y, total - 1), c = min(z, total - b) but also c >= 1
// Actually b+c <= total means we pick b+c = min(total, y+z) optimally
// For fixed sum s = b+c, maximize b*c: b = s/2, c = s - s/2 (balanced)
// But with constraints b <= y, c <= z
// Best approach: iterate cx from 0 to min(k, maxX)
// but maxX can be 10^6, so that's fine
best := int64(0)
for cx := int64(0); cx <= maxX && cx <= k; cx++ {
remaining := k - cx
// Now distribute remaining between y and z axes
// cuts on y: cy <= maxY, cuts on z: cz <= maxZ, cy + cz <= remaining
// maximize (cy+1)*(cz+1)
// Let a = cy+1 (1..y), b = cz+1 (1..z), a+b <= remaining+2
// total available = remaining + 2
total := remaining + 2
// Optimal split: a = min(y, floor(total/2) or ceil)
// but constrained by y and z
// if total >= y+z, then a=y, b=z
// else distribute as evenly as possible
var a, b int64
if total >= y+z {
a = y
b = z
} else {
a = total / 2
if a > y {
a = y
}
b = total - a
if b > z {
b = z
a = total - b
if a > y {
a = y
}
}
}
if a < 1 {
a = 1
}
if b < 1 {
b = 1
}
pieces := (cx + 1) * a * b
if pieces > best {
best = pieces
}
}
fmt.Println(best)
}
```