← Home
package main

import (
	"io"
	"math/bits"
	"os"
	"strconv"
)

type Cand struct {
	u int
	v int
	w int64
}

type State struct {
	d int64
	v int
}

type Edge struct {
	to   int
	rev  int
	cap  int
	cost int64
}

func nextInt(data []byte, idx *int) int {
	n := len(data)
	i := *idx
	for i < n && (data[i] < '0' || data[i] > '9') {
		i++
	}
	val := 0
	for i < n && data[i] >= '0' && data[i] <= '9' {
		val = val*10 + int(data[i]-'0')
		i++
	}
	*idx = i
	return val
}

func candUp(h []Cand, i int) {
	for i > 0 {
		p := (i - 1) >> 1
		if h[p].w <= h[i].w {
			break
		}
		h[p], h[i] = h[i], h[p]
		i = p
	}
}

func candDown(h []Cand, i int) {
	n := len(h)
	for {
		l := i*2 + 1
		if l >= n {
			break
		}
		m := l
		r := l + 1
		if r < n && h[r].w < h[l].w {
			m = r
		}
		if h[i].w <= h[m].w {
			break
		}
		h[i], h[m] = h[m], h[i]
		i = m
	}
}

func stateUp(h []State, i int) {
	for i > 0 {
		p := (i - 1) >> 1
		if h[p].d <= h[i].d {
			break
		}
		h[p], h[i] = h[i], h[p]
		i = p
	}
}

func stateDown(h []State, i int) {
	n := len(h)
	for {
		l := i*2 + 1
		if l >= n {
			break
		}
		m := l
		r := l + 1
		if r < n && h[r].d < h[l].d {
			m = r
		}
		if h[i].d <= h[m].d {
			break
		}
		h[i], h[m] = h[m], h[i]
		i = m
	}
}

func statePush(h *[]State, x State) {
	*h = append(*h, x)
	stateUp(*h, len(*h)-1)
}

func statePop(h *[]State) State {
	a := *h
	res := a[0]
	last := a[len(a)-1]
	a = a[:len(a)-1]
	if len(a) > 0 {
		a[0] = last
		stateDown(a, 0)
	}
	*h = a
	return res
}

func addEdge(g [][]Edge, u, v, cap int, cost int64) {
	g[u] = append(g[u], Edge{to: v, rev: len(g[v]), cap: cap, cost: cost})
	g[v] = append(g[v], Edge{to: u, rev: len(g[u]) - 1, cap: 0, cost: -cost})
}

func main() {
	data, _ := io.ReadAll(os.Stdin)
	idx := 0
	n := nextInt(data, &idx)
	k := nextInt(data, &idx)

	m := 1 << n
	a := make([]int, m)
	for i := 0; i < m; i++ {
		a[i] = nextInt(data, &idx)
	}

	B := (2*n - 1) * k
	top := make([]Cand, 0, B)
	limit := m - 1

	for u := 0; u < m; u++ {
		au := a[u]
		mask := (^u) & limit
		for mask != 0 {
			b := bits.TrailingZeros(uint(mask))
			v := u | (1 << b)
			w := int64(au + a[v])
			if len(top) < B {
				top = append(top, Cand{u: u, v: v, w: w})
				candUp(top, len(top)-1)
			} else if w > top[0].w {
				top[0] = Cand{u: u, v: v, w: w}
				candDown(top, 0)
			}
			mask &= mask - 1
		}
	}

	if len(top) == 0 {
		os.Stdout.WriteString("0")
		return
	}

	type CE struct {
		l int
		r int
		w int64
	}

	leftID := make(map[int]int, len(top))
	rightID := make(map[int]int, len(top))
	edges := make([]CE, 0, len(top))
	var maxW int64

	for _, c := range top {
		u, v := c.u, c.v
		if bits.OnesCount(uint(u))&1 == 1 {
			u, v = v, u
		}
		li, ok := leftID[u]
		if !ok {
			li = len(leftID)
			leftID[u] = li
		}
		ri, ok := rightID[v]
		if !ok {
			ri = len(rightID)
			rightID[v] = ri
		}
		edges = append(edges, CE{l: li, r: ri, w: c.w})
		if c.w > maxW {
			maxW = c.w
		}
	}

	L := len(leftID)
	R := len(rightID)
	src := 0
	sink := 1 + L + R
	N := sink + 1

	g := make([][]Edge, N)
	for i := 0; i < L; i++ {
		addEdge(g, src, 1+i, 1, 0)
	}
	for i := 0; i < R; i++ {
		addEdge(g, 1+L+i, sink, 1, 0)
	}
	for _, e := range edges {
		addEdge(g, 1+e.l, 1+L+e.r, 1, -e.w)
	}

	pot := make([]int64, N)
	for i := 0; i < R; i++ {
		pot[1+L+i] = -maxW
	}
	pot[sink] = -maxW

	const inf int64 = 1 << 60
	dist := make([]int64, N)
	pv := make([]int, N)
	pe := make([]int, N)

	var curCost int64
	var bestCost int64

	for flow := 0; flow < k; flow++ {
		for i := 0; i < N; i++ {
			dist[i] = inf
			pv[i] = -1
			pe[i] = -1
		}
		dist[src] = 0
		pq := make([]State, 0, N)
		statePush(&pq, State{d: 0, v: src})

		for len(pq) > 0 {
			cur := statePop(&pq)
			if cur.d != dist[cur.v] {
				continue
			}
			if cur.v == sink {
				break
			}
			for i, e := range g[cur.v] {
				if e.cap == 0 {
					continue
				}
				nd := cur.d + e.cost + pot[cur.v] - pot[e.to]
				if nd < dist[e.to] {
					dist[e.to] = nd
					pv[e.to] = cur.v
					pe[e.to] = i
					statePush(&pq, State{d: nd, v: e.to})
				}
			}
		}

		if dist[sink] == inf {
			break
		}

		pathCost := dist[sink] + pot[sink] - pot[src]
		for i := 0; i < N; i++ {
			if dist[i] < inf {
				pot[i] += dist[i]
			}
		}

		v := sink
		for v != src {
			u := pv[v]
			ei := pe[v]
			g[u][ei].cap--
			rev := g[u][ei].rev
			g[v][rev].cap++
			v = u
		}

		curCost += pathCost
		if curCost < bestCost {
			bestCost = curCost
		}
	}

	os.Stdout.WriteString(strconv.FormatInt(-bestCost, 10))
}