```go
package main
import (
"bufio"
"container/heap"
"fmt"
"math"
"os"
)
type Option struct {
lnT float64
lnU float64
}
type Upgrade struct {
delta float64
i int
next int
index int
}
type MinHeap []*Upgrade
func (h MinHeap) Len() int { return len(h) }
func (h MinHeap) Less(i, j int) bool { return h[i].delta < h[j].delta }
func (h MinHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i]; h[i].index = i; h[j].index = j }
func (h *MinHeap) Push(x interface{}) { *h = append(*h, x.(*Upgrade)) }
func (h *MinHeap) Pop() interface{} {
old := *h
n := len(old)
it := old[n-1]
*h = old[:n-1]
return it
}
func genOptions(a int64) []Option {
opts := make([]Option, 0, 2*int(math.Sqrt(float64(a)))+5)
for l := int64(1); l <= a; {
t := a / l
r := a / t
opts = append(opts, Option{
lnT: math.Log(float64(t)),
lnU: math.Log(float64(r)),
})
l = r + 1
}
return opts
}
func main() {
in := bufio.NewReader(os.Stdin)
var n int
var k int64
if _, err := fmt.Fscan(in, &n, &k); err != nil {
return
}
a := make([]int64, n)
for i := 0; i < n; i++ {
fmt.Fscan(in, &a[i])
}
if k <= 0 {
fmt.Printf("0\n")
return
}
opts := make([][]Option, n)
sumLnA := 0.0
for i := 0; i < n; i++ {
opts[i] = genOptions(a[i])
sumLnA += math.Log(float64(a[i]))
}
lnK := math.Log(float64(k))
if sumLnA+1e-15 < lnK {
fmt.Printf("0\n")
return
}
// Binary search on lambda
l, r := 0.0, 100.0
for it := 0; it < 80; it++ {
mid := (l + r) / 2
sumU := 0.0
for i := 0; i < n; i++ {
best := -1e300
bestU := 0.0
oi := opts[i]
for j := 0; j < len(oi); j++ {
val := oi[j].lnT + mid*oi[j].lnU
if val > best {
best = val
bestU = oi[j].lnU
}
}
sumU += bestU
}
if sumU >= lnK {
r = mid
} else {
l = mid
}
}
// Tie-aware selection at lambda = r
eps := 1e-12
sumU := 0.0
sumT := 0.0
curIdx := make([]int, n)
cands := make([][]int, n)
for i := 0; i < n; i++ {
oi := opts[i]
best := -1e300
for j := 0; j < len(oi); j++ {
val := oi[j].lnT + r*oi[j].lnU
if val > best {
best = val
}
}
// collect near-max candidates
tmp := make([]int, 0, 3)
for j := 0; j < len(oi); j++ {
val := oi[j].lnT + r*oi[j].lnU
if val >= best-eps {
tmp = append(tmp, j)
}
}
// sort tmp by lnU ascending (small list, insertion sort)
for x := 1; x < len(tmp); x++ {
kx := tmp[x]
y := x - 1
for y >= 0 && oi[tmp[y]].lnU > oi[kx].lnU {
tmp[y+1] = tmp[y]
y--
}
tmp[y+1] = kx
}
cands[i] = tmp
curIdx[i] = 0
sumU += oi[tmp[0]].lnU
sumT += oi[tmp[0]].lnT
}
if sumU+1e-15 < lnK {
h := &MinHeap{}
heap.Init(h)
for i := 0; i < n; i++ {
if len(cands[i]) >= 2 {
oi := opts[i]
j0 := cands[i][0]
j1 := cands[i][1]
heap.Push(h, &Upgrade{
delta: oi[j1].lnU - oi[j0].lnU,
i: i,
next: 1,
})
}
}
for sumU+1e-15 < lnK && h.Len() > 0 {
u := heap.Pop(h).(*Upgrade)
i := u.i
prev := cands[i][curIdx[i]]
curIdx[i] = u.next
now := cands[i][curIdx[i]]
sumU += opts[i][now].lnU - opts[i][prev].lnU
sumT += opts[i][now].lnT - opts[i][prev].lnT
if curIdx[i]+1 < len(cands[i]) {
jc := cands[i][curIdx[i]]
jn := cands[i][curIdx[i]+1]
heap.Push(h, &Upgrade{
delta: opts[i][jn].lnU - opts[i][jc].lnU,
i: i,
next: curIdx[i] + 1,
})
}
}
// If still not enough due to numerical issues, slightly increase lambda and recompute greedily
if sumU+1e-12 < lnK {
rr := r + 1e-9
sumU = 0.0
sumT = 0.0
for i := 0; i < n; i++ {
oi := opts[i]
best := -1e300
bestU := 0.0
bestT := 0.0
for j := 0; j < len(oi); j++ {
val := oi[j].lnT + rr*oi[j].lnU
if val > best {
best = val
bestU = oi[j].lnU
bestT = oi[j].lnT
}
}
sumU += bestU
sumT += bestT
}
}
}
lnRes := math.Log(float64(k)) + sumT - sumLnA
res := math.Exp(lnRes)
fmt.Printf("%.12f\n", res)
}
```