← Home
```go
package main

import (
	"bufio"
	"fmt"
	"math"
	"math/bits"
	"os"
	"sort"
	"strconv"
)

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	scanner.Split(bufio.ScanWords)
	buf := make([]byte, 1024*1024)
	scanner.Buffer(buf, 1024*1024*10)

	if !scanner.Scan() {
		return
	}
	n, _ := strconv.Atoi(scanner.Text())
	if !scanner.Scan() {
		return
	}
	k, _ := strconv.Atoi(scanner.Text())

	h := make([]int64, n)
	var S int64
	for i := 0; i < n; i++ {
		scanner.Scan()
		h[i], _ = strconv.ParseInt(scanner.Text(), 10, 64)
		S += h[i]
	}

	sort.Slice(h, func(i, j int) bool { return h[i] < h[j] })

	unique_h := make([]int64, 0, n)
	counts := make([]int64, 0, n)
	for i := 0; i < n; i++ {
		if i == 0 || h[i] != h[i-1] {
			unique_h = append(unique_h, h[i])
			counts = append(counts, 1)
		} else {
			counts[len(counts)-1]++
		}
	}

	pref_counts := make([]int64, len(counts))
	pref_counts[0] = counts[0]
	for i := 1; i < len(counts); i++ {
		pref_counts[i] = pref_counts[i-1] + counts[i]
	}

	best_num := int64(-1)
	best_den := int64(-1)
	best_x := -1
	best_y := -1

	evaluated := make([]bool, k)

	lessFraction := func(num1, den1, num2, den2 int64) bool {
		hi1, lo1 := bits.Mul64(uint64(num1), uint64(den2))
		hi2, lo2 := bits.Mul64(uint64(num2), uint64(den1))
		if hi1 != hi2 {
			return hi1 < hi2
		}
		return lo1 < lo2
	}

	update := func(x int) {
		if x <= 0 || x >= k {
			return
		}
		if evaluated[x] {
			return
		}
		evaluated[x] = true

		var sum int64
		M := unique_h[len(unique_h)-1]
		U := int64(len(unique_h))

		cost1 := U
		cost2 := (M / int64(x)) * 5

		if cost1 <= cost2 {
			limit := int64(x)
			left, right := 0, len(unique_h)-1
			idx := -1
			for left <= right {
				mid := left + (right-left)/2
				if unique_h[mid] <= limit {
					idx = mid
					left = mid + 1
				} else {
					right = mid - 1
				}
			}
			if idx != -1 {
				sum += pref_counts[idx]
			}
			for i := idx + 1; i < len(unique_h); i++ {
				sum += counts[i] * ((unique_h[i] + int64(x) - 1) / int64(x))
			}
		} else {
			last_idx := -1
			c := int64(1)
			for {
				limit := c * int64(x)
				left, right := last_idx+1, len(unique_h)-1
				idx := last_idx
				for left <= right {
					mid := left + (right-left)/2
					if unique_h[mid] <= limit {
						idx = mid
						left = mid + 1
					} else {
						right = mid - 1
					}
				}
				if idx > last_idx {
					var count_in_range int64
					if last_idx == -1 {
						count_in_range = pref_counts[idx]
					} else {
						count_in_range = pref_counts[idx] - pref_counts[last_idx]
					}
					sum += count_in_range * c
					last_idx = idx
				}
				if last_idx == len(unique_h)-1 {
					break
				}
				c++
			}
		}

		y := k - x
		if best_num == -1 || lessFraction(sum, int64(y), best_num, best_den) {
			best_num = sum
			best_den = int64(y)
			best_x = x
			best_y = y
		}
	}

	S_float := float64(S)
	n_float := float64(n)
	k_float := float64(k)
	discriminant := S_float*S_float + n_float*S_float*k_float
	x_opt_float := (-S_float + math.Sqrt(discriminant)) / n_float
	x_opt := int(x_opt_float)

	candidates := []int{1, k / 2, k - 1, x_opt, x_opt - 1, x_opt + 1}
	for _, x := range candidates {
		update(x)
	}

	for x := 1; x < k; x++ {
		if evaluated[x] {
			continue
		}
		lower_bound := (S + int64(x) - 1) / int64(x)
		if best_num != -1 && !lessFraction(lower_bound, int64(k-x), best_num, best_den) {
			continue
		}
		update(x)
	}

	fmt.Printf("%d %d\n", best_x, best_y)
}
```