← Home
```go
package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	reader := bufio.NewReader(os.Stdin)
	writer := bufio.NewWriter(os.Stdout)
	defer writer.Flush()

	var n int
	fmt.Fscan(reader, &n)

	cnt := make([]int, 5005)
	for i := 0; i < n; i++ {
		var k int
		fmt.Fscan(reader, &k)
		if k > 5000 {
			k = 5000
		}
		cnt[k]++
	}

	// Prefix sums for O(1) range queries
	pref := make([]int, 5005)
	current := 0
	for i := 0; i <= 5000; i++ {
		current += cnt[i]
		pref[i] = current
	}

	getSum := func(l, r int) int {
		if l > r {
			return 0
		}
		res := pref[r]
		if l > 0 {
			res -= pref[l-1]
		}
		return res
	}

	// Sieve primes
	isPrime := make([]bool, 5005)
	for i := 2; i <= 5000; i++ {
		isPrime[i] = true
	}
	primes := []int{}
	for i := 2; i <= 5000; i++ {
		if isPrime[i] {
			primes = append(primes, i)
			for j := i * i; j <= 5000; j += i {
				isPrime[j] = false
			}
		}
	}

	// Legendre's formula
	getPrimeCount := func(n, p int) int {
		c := 0
		for n > 0 {
			c += n / p
			n /= p
		}
		return c
	}

	var currentCost int64 = 0
	// Calculate initial cost (sum of all path lengths to root)
	for _, p := range primes {
		var pCost int64 = 0
		for k := 1; k <= 5000; k++ {
			if cnt[k] > 0 {
				pCost += int64(cnt[k]) * int64(getPrimeCount(k, p))
			}
		}
		currentCost += pCost
	}

	L, R := 0, 5000

	// Iterate primes descending
	for i := len(primes) - 1; i >= 0; i-- {
		p := primes[i]
		currentTaken := 0

		for {
			// Find smallest M in [L, R] such that E_p(M!) > currentTaken
			low, high := L, R
			M := -1
			for low <= high {
				mid := (low + high) / 2
				if getPrimeCount(mid, p) > currentTaken {
					M = mid
					high = mid - 1
				} else {
					low = mid + 1
				}
			}

			if M == -1 {
				// No group supports taking more p, proceed to next prime
				break
			}

			// M found. Support group for taking p is [M, R].
			support := getSum(M, R)

			if support*2 > n {
				// Majority wants p
				currentCost -= int64(2*support - n)
				L = M
				currentTaken++
			} else {
				// Majority does not want p.
				// Check if majority wants to switch (next prime)
				// Switch group: [L, M-1]
				switchGroup := getSum(L, M-1)
				if switchGroup*2 > n {
					R = M - 1
					break // break inner loop, continue to next prime
				} else {
					// Median found
					fmt.Fprintln(writer, currentCost)
					return
				}
			}
		}
		if L > R {
			break
		}
	}

	fmt.Fprintln(writer, currentCost)
}
```