// package QS.AA.NetworkFlow;

// F. Anti-Palindromize
// https://codeforces.com/contest/884/problem/F

import java.io.*;
import java.util.*;
public class CF_884F {

	public static final int MOD = 1000_000_000 + 7;
	public static final double EPS = 1e-6;
	public static final boolean DEBUG = true;

	public static void main(String[] args) throws java.io.IOException {
		final java.io.BufferedReader br = new java.io.BufferedReader(new java.io.InputStreamReader(System.in));

		int n = Integer.parseInt(br.readLine());
		char[] s = br.readLine().trim().toCharArray();
		String[] tokens = br.readLine().trim().split("\\s");
		int[] beauty = new int[n];

		int ans = 0;
		int m = 0, x = 0, t = 0;
		int[] b = new int[101];
		int[] count = new int[26];

		for (int i = 0; i < n; i++) {
			beauty[i] = Integer.parseInt(tokens[i]);
			ans += beauty[i];
		}

		for (int i = 0; i < n / 2; i++) {
			if (s[i] == s[n-i-1]) {
				t++;
				count[(int)(s[i] - 'a')]++;
				ans -= Math.min(beauty[i], beauty[n-i-1]);
			}
		}

		for (int i = 0; i < 26 ; i++) {
			if (m < count[i]) {
				m = count[i];
				x = i;
			}
		}

		if (2 * m <= t) {
			System.out.println(ans);
			return;
		}
		ArrayList<Integer> list = new ArrayList<Integer>();

		for (int i = 0; i < n/2; i++) {
			if ((int)(s[i] - 'a') != x && (int)(s[n-i-1] - 'a') != x && s[i] != s[n-i-1]) {
				list.add(Math.min(beauty[i], beauty[n-i-1]));
			}
		}

		Collections.sort(list);
		for (int i = 0; i < 2 * m - t; i++) {
			ans -= list.get(i);
		}
		System.out.print(ans);
	}
}


// practice with rainboy
import java.io.*;
import java.util.*;

public class CF884F extends PrintWriter {
	CF884F() { super(System.out, true); }
	Scanner sc = new Scanner(System.in);
	public static void main(String[] $) {
		CF884F o = new CF884F(); o.main(); o.flush();
	}

	static final int A = 26, INF = 0x3f3f3f3f;
	int[] oo, oh; int __ = 1;
	int link(int o, int h) {
		oo[__] = o; oh[__] = h;
		return __++;
	}
	int[] ii, jj, cc, ww, ww_; int m_;
	int[] ae, dd, kk, ff; int n_;
	int[] pq, iq; int cnt;
	void init() {
		oo = new int[1 + m_ * 2]; oh = new int[1 + m_ * 2];
		ii = new int[m_]; jj = new int[m_];
		cc = new int[m_ << 1];
		ww = new int[m_]; ww_ = new int[m_];
		ae = new int[n_];
		dd = new int[n_]; kk = new int[n_]; ff = new int[n_];
		pq = new int[1 + n_]; iq = new int[n_];
		m_ = 0;
	}
	void link_(int i, int j, int c, int w) {
		int h = m_++;
		ii[h] = i; jj[h] = j; cc[h << 1] = c; ww[h] = w;
		ae[i] = link(ae[i], h << 1);
		ae[j] = link(ae[j], h << 1 | 1);
	}
	boolean less(int u, int v) {
		return dd[u] < dd[v] || dd[u] == dd[v] && kk[u] < kk[v];
	}
	int i2(int i) {
		return (i *= 2) > cnt ? 0 : i < cnt && less(pq[i + 1], pq[i]) ? i + 1 : i;
	}
	void pq_up(int u) {
		int i, j, v;
		for (i = iq[u]; (j = i / 2) > 0 && less(u, v = pq[j]); i = j)
			pq[iq[v] = i] = v;
		pq[iq[u] = i] = u;
	}
	void pq_dn(int u) {
		int i, j, v;
		for (i = iq[u]; (j = i2(i)) > 0 && less(v = pq[j], u); i = j)
			pq[iq[v] = i] = v;
		pq[iq[u] = i] = u;
	}
	void pq_add_last(int u) {
		pq[iq[u] = ++cnt] = u;
	}
	int pq_remove_first() {
		int u = pq[1], v = pq[cnt--];
		if (v != u) {
			iq[v] = 1; pq_dn(v);
		}
		iq[u] = 0;
		return u;
	}
	boolean dijkstra(int s, int t) {
		Arrays.fill(dd, INF);
		dd[s] = 0; pq_add_last(s);
		while (cnt > 0) {
			int i = pq_remove_first();
			int k = kk[i] + 1;
			for (int o = ae[i]; o != 0; o = oo[o]) {
				int h_ = oh[o];
				if (cc[h_] > 0) {
					int h = h_ >> 1;
					int j = i ^ ii[h] ^ jj[h];
					int d = dd[i] + ((h_ & 1) == 0 ? ww_[h] : -ww_[h]);
					if (dd[j] > d || dd[j] == d && kk[j] > k) {
						if (dd[j] == INF)
							pq_add_last(j);
						dd[j] = d; kk[j] = k; ff[j] = h_;
						pq_up(j);
					}
				}
			}
		}
		return dd[t] != INF;
	}
	int trace(int s, int t) {
		while (t != s) {
			int h_ = ff[t], h = h_ >> 1;
			cc[h_]--; cc[h_ ^ 1]++;
			t ^= ii[h] ^ jj[h];
		}
		return 1;
	}
	int edmonds_karp(int s, int t) {
		for (int h = 0; h < m_; h++) {
			int i = ii[h], j = jj[h];
			dd[j] = Math.min(dd[j], dd[i] + ww[h]);
		}
		for (int h = 0; h < m_; h++) {
			int i = ii[h], j = jj[h];
			ww_[h] = ww[h] + dd[i] - dd[j];
		}
		int f = 0;
		while (dijkstra(s, t)) {
			f += trace(s, t);
			for (int h = 0; h < m_; h++) {
				int i = ii[h], j = jj[h];
				if (dd[i] != INF && dd[j] != INF) {
					// dd[j] <= dd[i] + ww_[h]
					// ww_[h] + dd[i] - dd[j] >= 0
					ww_[h] += dd[i] - dd[j];
				}
			}
		}
		int cost = 0;
		for (int h = 0; h < m_; h++)
			cost += ww[h] * cc[h << 1 | 1];
		return cost;
	}
	void main() {
		int n = sc.nextInt() / 2;
		n_ = 1 + n + A + 1;
		m_ = n + n * A + A;
		init();
		byte[] cc = sc.next().getBytes();
		int[] bb = new int[n * 2];
		for (int i = 0; i < n * 2; i++)
			bb[i] = sc.nextInt();
		for (int i = 0; i < n; i++)
			link_(0, 1 + i, 2, 0);
		for (int i = 0; i < n; i++) {
			int j = n * 2 - 1 - i;
			int ai = cc[i] - 'a';
			int aj = cc[j] - 'a';
			for (int a = 0; a < A; a++) {
				int b;
				if (a == ai && a == aj)
					b = Math.max(bb[i], bb[j]);
				else if (a == ai)
					b = bb[i];
				else if (a == aj)
					b = bb[j];
				else
					b = 0;
				link_(1 + i, 1 + n + a, 1, -b);
			}
		}
		int[] kk = new int[A];
		for (int i = 0; i < n * 2; i++) {
			int a = cc[i] - 'a';
			kk[a]++;
		}
		for (int a = 0; a < A; a++)
			link_(1 + n + a, n_ - 1, kk[a], 0);
		println(-edmonds_karp(0, n_ - 1));
	}
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.InputMismatchException;
import java.io.OutputStreamWriter;
import java.util.NoSuchElementException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Iterator;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.Writer;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author Junior
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        OutputWriter out = new OutputWriter(outputStream);
        TaskF solver = new TaskF();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskF {
        public void solve(int testNumber, InputReader in, OutputWriter out) {
            int n = in.nextInt();
            String s = in.nextString();
            int[] a = new int[n];
            int[] cnt = new int[26];
            for (int i = 0; i < n; ++i) {
                a[i] = in.nextInt();
                cnt[(int) s.charAt(i) - 'a']++;
            }
            Graph g = new Graph(n + 100);
            int source = n + 100 - 2, target = source + 1;
            for (int i = 0; i * 2 < n; ++i) g.addFlowWeightedEdge(i, target, 0, 2);
            for (int i = 0; i < 26; ++i) {
                g.addFlowWeightedEdge(source, i + n, 0, cnt[i]);
                for (int j = 0; j * 2 < n; ++j) {
                    if (s.charAt(j) == s.charAt(n - j - 1)) {
                        int w = 0;
                        if (s.charAt(j) == i + 'a') w = -Math.max(a[j], a[n - j - 1]);
                        g.addFlowWeightedEdge(i + n, j, w, 1);
                    } else {
                        int w = 0;
                        if (s.charAt(j) == i + 'a') w -= a[j];
                        if (s.charAt(n - j - 1) == i + 'a') w -= a[n - j - 1];
                        g.addFlowWeightedEdge(i + n, j, w, 1);
                    }
                }
            }
            MinCostFlow mcmf = new MinCostFlow(g, source, target, true);
            out.println(-mcmf.minCostMaxFlow().first);

        }

    }

    static interface IntComparator {
        public static final IntComparator DEFAULT = (first, second) -> {
            if (first < second) {
                return -1;
            }
            if (first > second) {
                return 1;
            }
            return 0;
        };

        public int compare(int first, int second);

    }

    static interface IntStream extends Iterable<Integer>, Comparable<IntStream> {
        public IntIterator intIterator();

        default public Iterator<Integer> iterator() {
            return new Iterator<Integer>() {
                private IntIterator it = intIterator();

                public boolean hasNext() {
                    return it.isValid();
                }

                public Integer next() {
                    int result = it.value();
                    it.advance();
                    return result;
                }
            };
        }

        default public int compareTo(IntStream c) {
            IntIterator it = intIterator();
            IntIterator jt = c.intIterator();
            while (it.isValid() && jt.isValid()) {
                int i = it.value();
                int j = jt.value();
                if (i < j) {
                    return -1;
                } else if (i > j) {
                    return 1;
                }
                it.advance();
                jt.advance();
            }
            if (it.isValid()) {
                return 1;
            }
            if (jt.isValid()) {
                return -1;
            }
            return 0;
        }

    }

    static class Graph {
        public static final int REMOVED_BIT = 0;
        protected int vertexCount;
        protected int edgeCount;
        private int[] firstOutbound;
        private int[] firstInbound;
        private Edge[] edges;
        private int[] nextInbound;
        private int[] nextOutbound;
        private int[] from;
        private int[] to;
        private long[] weight;
        public long[] capacity;
        private int[] reverseEdge;
        private int[] flags;

        public Graph(int vertexCount) {
            this(vertexCount, vertexCount);
        }

        public Graph(int vertexCount, int edgeCapacity) {
            this.vertexCount = vertexCount;
            firstOutbound = new int[vertexCount];
            Arrays.fill(firstOutbound, -1);

            from = new int[edgeCapacity];
            to = new int[edgeCapacity];
            nextOutbound = new int[edgeCapacity];
            flags = new int[edgeCapacity];
        }

        public int addEdge(int fromID, int toID, long weight, long capacity, int reverseEdge) {
            ensureEdgeCapacity(edgeCount + 1);
            if (firstOutbound[fromID] != -1) {
                nextOutbound[edgeCount] = firstOutbound[fromID];
            } else {
                nextOutbound[edgeCount] = -1;
            }
            firstOutbound[fromID] = edgeCount;
            if (firstInbound != null) {
                if (firstInbound[toID] != -1) {
                    nextInbound[edgeCount] = firstInbound[toID];
                } else {
                    nextInbound[edgeCount] = -1;
                }
                firstInbound[toID] = edgeCount;
            }
            this.from[edgeCount] = fromID;
            this.to[edgeCount] = toID;
            if (capacity != 0) {
                if (this.capacity == null) {
                    this.capacity = new long[from.length];
                }
                this.capacity[edgeCount] = capacity;
            }
            if (weight != 0) {
                if (this.weight == null) {
                    this.weight = new long[from.length];
                }
                this.weight[edgeCount] = weight;
            }
            if (reverseEdge != -1) {
                if (this.reverseEdge == null) {
                    this.reverseEdge = new int[from.length];
                    Arrays.fill(this.reverseEdge, 0, edgeCount, -1);
                }
                this.reverseEdge[edgeCount] = reverseEdge;
            }
            if (edges != null) {
                edges[edgeCount] = createEdge(edgeCount);
            }
            return edgeCount++;
        }

        protected final GraphEdge createEdge(int id) {
            return new GraphEdge(id);
        }

        public final int addFlowWeightedEdge(int from, int to, long weight, long capacity) {
            if (capacity == 0) {
                return addEdge(from, to, weight, 0, -1);
            } else {
                int lastEdgeCount = edgeCount;
                addEdge(to, from, -weight, 0, lastEdgeCount + entriesPerEdge());
                return addEdge(from, to, weight, capacity, lastEdgeCount);
            }
        }

        protected int entriesPerEdge() {
            return 1;
        }

        public final int vertexCount() {
            return vertexCount;
        }

        public final int firstOutbound(int vertex) {
            int id = firstOutbound[vertex];
            while (id != -1 && isRemoved(id)) {
                id = nextOutbound[id];
            }
            return id;
        }

        public final int nextOutbound(int id) {
            id = nextOutbound[id];
            while (id != -1 && isRemoved(id)) {
                id = nextOutbound[id];
            }
            return id;
        }

        public final int source(int id) {
            return from[id];
        }

        public final int destination(int id) {
            return to[id];
        }

        public final long weight(int id) {
            if (weight == null) {
                return 0;
            }
            return weight[id];
        }

        public final long capacity(int id) {
            if (capacity == null) {
                return 0;
            }
            return capacity[id];
        }

        public final long flow(int id) {
            if (reverseEdge == null) {
                return 0;
            }
            return capacity[reverseEdge[id]];
        }

        public final void pushFlow(int id, long flow) {
            if (flow == 0) {
                return;
            }
            if (flow > 0) {
                if (capacity(id) < flow) {
                    throw new IllegalArgumentException("Not enough capacity");
                }
            } else {
                if (flow(id) < -flow) {
                    throw new IllegalArgumentException("Not enough capacity");
                }
            }
            capacity[id] -= flow;
            capacity[reverseEdge[id]] += flow;
        }

        public final boolean flag(int id, int bit) {
            return (flags[id] >> bit & 1) != 0;
        }

        public final boolean isRemoved(int id) {
            return flag(id, REMOVED_BIT);
        }

        protected void ensureEdgeCapacity(int size) {
            if (from.length < size) {
                int newSize = Math.max(size, 2 * from.length);
                if (edges != null) {
                    edges = resize(edges, newSize);
                }
                from = resize(from, newSize);
                to = resize(to, newSize);
                nextOutbound = resize(nextOutbound, newSize);
                if (nextInbound != null) {
                    nextInbound = resize(nextInbound, newSize);
                }
                if (weight != null) {
                    weight = resize(weight, newSize);
                }
                if (capacity != null) {
                    capacity = resize(capacity, newSize);
                }
                if (reverseEdge != null) {
                    reverseEdge = resize(reverseEdge, newSize);
                }
                flags = resize(flags, newSize);
            }
        }

        protected final int[] resize(int[] array, int size) {
            int[] newArray = new int[size];
            System.arraycopy(array, 0, newArray, 0, array.length);
            return newArray;
        }

        private long[] resize(long[] array, int size) {
            long[] newArray = new long[size];
            System.arraycopy(array, 0, newArray, 0, array.length);
            return newArray;
        }

        private Edge[] resize(Edge[] array, int size) {
            Edge[] newArray = new Edge[size];
            System.arraycopy(array, 0, newArray, 0, array.length);
            return newArray;
        }

        public final boolean isSparse() {
            return vertexCount == 0 || edgeCount * 20 / vertexCount <= vertexCount;
        }

        protected class GraphEdge implements Edge {
            protected int id;

            protected GraphEdge(int id) {
                this.id = id;
            }

        }

    }

    static interface IntCollection extends IntStream {
    }

    static class MinCostFlow {
        private final Graph graph;
        private final int source;
        private final int destination;
        private final long[] phi;
        private final long[] dijkstraResult;
        private final int[] lastEdge;
        private final Heap heap;
        private final int vertexCount;
        private final int[] visited;
        private int visitIndex;

        public MinCostFlow(Graph graph, int source, int destination, boolean hasNegativeEdges) {
            this.graph = graph;
            this.source = source;
            this.destination = destination;
            vertexCount = graph.vertexCount();
            phi = new long[vertexCount];
            if (hasNegativeEdges) {
                fordBellman();
            }
            dijkstraResult = new long[vertexCount];
            lastEdge = new int[vertexCount];
            if (graph.isSparse()) {
                heap = new Heap(vertexCount, new IntComparator() {
                    public int compare(int first, int second) {
                        return IntegerUtils.longCompare(dijkstraResult[first], dijkstraResult[second]);
                    }
                }, vertexCount);
                visited = null;
            } else {
                heap = null;
                visited = new int[vertexCount];
            }
        }

        private void fordBellman() {
            Arrays.fill(phi, Long.MAX_VALUE);
            phi[source] = 0;
            boolean[] inQueue = new boolean[vertexCount];
            int[] queue = new int[vertexCount + 1];
            queue[0] = source;
            inQueue[source] = true;
            int stepCount = 0;
            int head = 0;
            int end = 1;
            int maxSteps = 2 * vertexCount * vertexCount;
            while (head != end) {
                int vertex = queue[head++];
                if (head == queue.length) {
                    head = 0;
                }
                inQueue[vertex] = false;
                int edgeID = graph.firstOutbound(vertex);
                while (edgeID != -1) {
                    long total = phi[vertex] + graph.weight(edgeID);
                    int destination = graph.destination(edgeID);
                    if (graph.capacity(edgeID) != 0 && phi[destination] > total) {
                        phi[destination] = total;
                        if (!inQueue[destination]) {
                            queue[end++] = destination;
                            inQueue[destination] = true;
                            if (end == queue.length) {
                                end = 0;
                            }
                        }
                    }
                    edgeID = graph.nextOutbound(edgeID);
                }
                if (++stepCount > maxSteps) {
                    throw new IllegalArgumentException("Graph contains negative cycle");
                }
            }
        }

        public Pair<Long, Long> minCostMaxFlow() {
            return minCostMaxFlow(Long.MAX_VALUE);
        }

        public Pair<Long, Long> minCostMaxFlow(long maxFlow) {
            long cost = 0;
            long flow = 0;
            while (maxFlow != 0) {
                if (graph.isSparse()) {
                    dijkstraAlgorithm();
                } else {
                    dijkstraAlgorithmFull();
                }
                if (lastEdge[destination] == -1) {
                    return Pair.makePair(cost, flow);
                }
                for (int i = 0; i < dijkstraResult.length; i++) {
                    if (dijkstraResult[i] != Long.MAX_VALUE) {
                        phi[i] += dijkstraResult[i];
                    }
                }
                int vertex = destination;
                long currentFlow = maxFlow;
                long currentCost = 0;
                while (vertex != source) {
                    int edgeID = lastEdge[vertex];
                    currentFlow = Math.min(currentFlow, graph.capacity(edgeID));
                    currentCost += graph.weight(edgeID);
                    vertex = graph.source(edgeID);
                }
                maxFlow -= currentFlow;
                cost += currentCost * currentFlow;
                flow += currentFlow;
                vertex = destination;
                while (vertex != source) {
                    int edgeID = lastEdge[vertex];
                    graph.pushFlow(edgeID, currentFlow);
                    vertex = graph.source(edgeID);
                }
            }
            return Pair.makePair(cost, flow);
        }

        private void dijkstraAlgorithm() {
            Arrays.fill(dijkstraResult, Long.MAX_VALUE);
            Arrays.fill(lastEdge, -1);
            dijkstraResult[source] = 0;
            heap.add(source);
            while (!heap.isEmpty()) {
                int current = heap.poll();
                int edgeID = graph.firstOutbound(current);
                while (edgeID != -1) {
                    if (graph.capacity(edgeID) != 0) {
                        int next = graph.destination(edgeID);
                        long total = graph.weight(edgeID) - phi[next] + phi[current] + dijkstraResult[current];
                        if (dijkstraResult[next] > total) {
                            dijkstraResult[next] = total;
                            if (heap.getIndex(next) == -1) {
                                heap.add(next);
                            } else {
                                heap.shiftUp(heap.getIndex(next));
                            }
                            lastEdge[next] = edgeID;
                        }
                    }
                    edgeID = graph.nextOutbound(edgeID);
                }
            }
        }

        private void dijkstraAlgorithmFull() {
            visitIndex++;
            Arrays.fill(dijkstraResult, Long.MAX_VALUE);
            lastEdge[destination] = -1;
            dijkstraResult[source] = 0;
            for (int i = 0; i < vertexCount; i++) {
                int index = -1;
                long length = Long.MAX_VALUE;
                for (int j = 0; j < vertexCount; j++) {
                    if (visited[j] != visitIndex && dijkstraResult[j] < length) {
                        length = dijkstraResult[j];
                        index = j;
                    }
                }
                if (index == -1) {
                    return;
                }
                visited[index] = visitIndex;
                int edgeID = graph.firstOutbound(index);
                while (edgeID != -1) {
                    if (graph.capacity(edgeID) != 0) {
                        int next = graph.destination(edgeID);
                        if (visited[next] != visitIndex) {
                            long total = graph.weight(edgeID) - phi[next] + phi[index] + length;
                            if (dijkstraResult[next] > total) {
                                dijkstraResult[next] = total;
                                lastEdge[next] = edgeID;
                            }
                        }
                    }
                    edgeID = graph.nextOutbound(edgeID);
                }
            }
        }

    }

    static interface Edge {
    }

    static class OutputWriter {
        private final PrintWriter writer;

        public OutputWriter(OutputStream outputStream) {
            writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
        }

        public OutputWriter(Writer writer) {
            this.writer = new PrintWriter(writer);
        }

        public void close() {
            writer.close();
        }

        public void println(long i) {
            writer.println(i);
        }

    }

    static interface IntQueue extends IntCollection {
    }

    static interface IntIterator {
        public int value() throws NoSuchElementException;

        public boolean advance();

        public boolean isValid();

    }

    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
        private InputReader.SpaceCharFilter filter;

        public InputReader(InputStream stream) {
            this.stream = stream;
        }

        public int read() {
            if (numChars == -1) {
                throw new InputMismatchException();
            }
            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (numChars <= 0) {
                    return -1;
                }
            }
            return buf[curChar++];
        }

        public int nextInt() {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
            }
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            int res = 0;
            do {
                if (c < '0' || c > '9') {
                    throw new InputMismatchException();
                }
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public String nextString() {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
            }
            StringBuilder res = new StringBuilder();
            do {
                if (Character.isValidCodePoint(c)) {
                    res.appendCodePoint(c);
                }
                c = read();
            } while (!isSpaceChar(c));
            return res.toString();
        }

        public boolean isSpaceChar(int c) {
            if (filter != null) {
                return filter.isSpaceChar(c);
            }
            return isWhitespace(c);
        }

        public static boolean isWhitespace(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

        public interface SpaceCharFilter {
            public boolean isSpaceChar(int ch);

        }

    }

    static class IntegerUtils {
        public static int longCompare(long a, long b) {
            if (a < b) {
                return -1;
            }
            if (a > b) {
                return 1;
            }
            return 0;
        }

    }

    static class Pair<U, V> implements Comparable<Pair<U, V>> {
        public final U first;
        public final V second;

        public static <U, V> Pair<U, V> makePair(U first, V second) {
            return new Pair<U, V>(first, second);
        }

        private Pair(U first, V second) {
            this.first = first;
            this.second = second;
        }

        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }

            Pair pair = (Pair) o;

            return !(first != null ? !first.equals(pair.first) : pair.first != null) &&
                    !(second != null ? !second.equals(pair.second) : pair.second != null);
        }

        public int hashCode() {
            int result = first != null ? first.hashCode() : 0;
            result = 31 * result + (second != null ? second.hashCode() : 0);
            return result;
        }

        public String toString() {
            return "(" + first + "," + second + ")";
        }

        @SuppressWarnings({"unchecked"})
        public int compareTo(Pair<U, V> o) {
            int value = ((Comparable<U>) first).compareTo(o.first);
            if (value != 0) {
                return value;
            }
            return ((Comparable<V>) second).compareTo(o.second);
        }

    }

    static class Heap implements IntQueue {
        private IntComparator comparator;
        private int size = 0;
        private int[] elements;
        private int[] at;

        public Heap(int maxElement) {
            this(10, maxElement);
        }

        public Heap(IntComparator comparator, int maxElement) {
            this(10, comparator, maxElement);
        }

        public Heap(int capacity, int maxElement) {
            this(capacity, IntComparator.DEFAULT, maxElement);
        }

        public Heap(int capacity, IntComparator comparator, int maxElement) {
            this.comparator = comparator;
            elements = new int[capacity];
            at = new int[maxElement];
            Arrays.fill(at, -1);
        }

        public boolean isEmpty() {
            return size == 0;
        }

        public void add(int element) {
            ensureCapacity(size + 1);
            elements[size] = element;
            at[element] = size;
            shiftUp(size++);
        }

        public void shiftUp(int index) {
            //		if (index < 0 || index >= size)
            //			throw new IllegalArgumentException();
            int value = elements[index];
            while (index != 0) {
                int parent = (index - 1) >>> 1;
                int parentValue = elements[parent];
                if (comparator.compare(parentValue, value) <= 0) {
                    elements[index] = value;
                    at[value] = index;
                    return;
                }
                elements[index] = parentValue;
                at[parentValue] = index;
                index = parent;
            }
            elements[0] = value;
            at[value] = 0;
        }

        public void shiftDown(int index) {
            if (index < 0 || index >= size) {
                throw new IllegalArgumentException();
            }
            while (true) {
                int child = (index << 1) + 1;
                if (child >= size) {
                    return;
                }
                if (child + 1 < size && comparator.compare(elements[child], elements[child + 1]) > 0) {
                    child++;
                }
                if (comparator.compare(elements[index], elements[child]) <= 0) {
                    return;
                }
                swap(index, child);
                index = child;
            }
        }

        public int getIndex(int element) {
            return at[element];
        }

        private void swap(int first, int second) {
            int temp = elements[first];
            elements[first] = elements[second];
            elements[second] = temp;
            at[elements[first]] = first;
            at[elements[second]] = second;
        }

        private void ensureCapacity(int size) {
            if (elements.length < size) {
                int[] oldElements = elements;
                elements = new int[Math.max(2 * elements.length, size)];
                System.arraycopy(oldElements, 0, elements, 0, this.size);
            }
        }

        public int poll() {
            if (isEmpty()) {
                throw new IndexOutOfBoundsException();
            }
            int result = elements[0];
            at[result] = -1;
            if (size == 1) {
                size = 0;
                return result;
            }
            elements[0] = elements[--size];
            at[elements[0]] = 0;
            shiftDown(0);
            return result;
        }

        public IntIterator intIterator() {
            return new IntIterator() {
                private int at;

                public int value() throws NoSuchElementException {
                    return elements[at];
                }

                public boolean advance() throws NoSuchElementException {
                    return ++at < size;
                }

                public boolean isValid() {
                    return at < size;
                }

                public void remove() throws NoSuchElementException {
                    throw new UnsupportedOperationException();
                }
            };
        }

    }
}


import java.util.*;

import static java.util.Arrays.stream;
import static java.util.stream.Collectors.toMap;

public class Main {
    static int n;
    static char[] chars;
    static int[] vals;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        n = sc.nextInt();
        sc.nextLine();
        String s = sc.nextLine().trim();
        chars = s.toCharArray();

        vals = new int[n];
        for (int i = 0; i < n; i ++) {
            vals[i] = sc.nextInt();
        }
        sc.nextLine();

        List<Char> wrongChars = new ArrayList<>();
        List<Char> chars1 = new ArrayList<>();
        for (int i = 0; i < n / 2; i++) {
            if (vals[i] > vals[n - i - 1]) {
                swap(i);
            }

            Char chr = new Char(chars[i], vals[i], i);
            if (chars[i] == chars[n - i - 1]) {
                wrongChars.add(chr);
            }
            chars1.add(chr);
        }
        chars1.sort(Comparator.comparing(c -> c.val));

        int diff = 0;
//        int[] vals1 = Arrays.copyOf(vals, n/2);
        if (!isAntiPalindrome(chars)) {
            if (wrongChars.size() == 1) {
                Char wrongChar = wrongChars.get(0);
                for (int i = 0; i < n/2; i++) {
                    Char chr = chars1.get(i);
                    if (chr.chr != wrongChar.chr && chars[n - chr.idx - 1] != wrongChar.chr) {
                        diff = wrongChar.val + chr.val;
                        break;
                    }
                }
            } else if (wrongChars.size() > 1) {
                Map<Character, Integer> map = wrongChars.stream().collect(toMap(n -> n.chr, n -> 1, (a, b) -> a+1, TreeMap::new));
                Map.Entry<Character, Integer> max = map.entrySet().stream().max(Comparator.comparing(Map.Entry::getValue)).get();
                List<Char> append = new ArrayList<>();
                while (max.getValue() * 2 > wrongChars.size() + append.size()) {
                    Character maxChar = max.getKey();
                    for (int i = 0; i < n/2; i++) {
                        Char chr = chars1.get(i);
                        if (chr.chr != maxChar && chars[n - chr.idx - 1] != maxChar && !wrongChars.contains(chr) && !append.contains(chr)) {
                            append.add(chr);
                            break;
                        }
                    }
                }
                diff = wrongChars.stream().mapToInt(chr -> chr.val).sum() + append.stream().mapToInt(chr -> chr.val).sum();
            }
        }

        int sum = stream(vals).sum();
        System.out.println(sum - diff);
    }

    private static void swap(int i) {
        char tmp = chars[i];
        chars[i] = chars[n - i - 1];
        chars[n - i - 1] = tmp;

        int tmpVal = vals[i];
        vals[i] = vals[n - i - 1];
        vals[n - i - 1] = tmpVal;
    }

    private static void swap(int i, int j) {
        char tmp = chars[i];
        chars[i] = chars[j];
        chars[j] = tmp;

        int tmpVal = vals[i];
        vals[i] = vals[n - i - 1];
        vals[n - i - 1] = tmpVal;
    }

    private static boolean isAntiPalindrome(char[] chars) {
        int n = chars.length;
        for (int i = 0; i < n/2; i++) {
            if (chars[i] == chars[n - i - 1]) {
                return false;
            }
        }
        return true;
    }

    static class Char {
        char chr;
        int val;
        int idx;

        Char(char chr, int val, int idx) {
            this.chr = chr;
            this.val = val;
            this.idx = idx;
        }

        @Override
        public String toString() {
            return "Char{" +
                    "chr=" + chr +
                    ", val=" + val +
                    ", idx=" + idx +
                    '}';
        }
    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.io.IOException;
import java.io.BufferedReader;
import java.util.Collections;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        AntiPalindrome solver = new AntiPalindrome();
        solver.solve(1, in, out);
        out.close();
    }

    static class AntiPalindrome {
        public void solve(int testNumber, InputReader in, PrintWriter out) {
            int N = in.nextInt();
            int[] cnt = new int[26];
            int move = 0;
            char[] str = in.next().toCharArray();
            int[] b = new int[N];
            int res = 0;
            for (int i = 0; i < b.length; i++) {
                b[i] = in.nextInt();
                res += b[i];
            }
            for (int i = 0; i < N / 2; i++) {
                if (str[i] == str[N - i - 1]) {
                    cnt[str[i] - 'a']++;
                    move++;
                    res -= Math.min(b[i], b[N - i - 1]);
                }
            }
            for (int i = 0; i < 26; i++) {
                if (cnt[i] > move / 2) {
                    int left = cnt[i] * 2 - move;
                    ArrayList<Integer> pos = new ArrayList<>();
                    for (int j = 0; j < N / 2; j++) {
                        if (str[j] != str[N - j - 1]) {
                            if (str[N - j - 1] - 'a' == i || str[j] - 'a' == i) {
//                            if (str[j] -'a' == i) {
//                                pos.add(b[j]);
//                            }
//                            else {
//                                pos.add(b[N-j-1]);
//                            }
                            } else {
                                pos.add(Math.min(b[N - j - 1], b[j]));
                            }
                        }
                    }
                    Collections.sort(pos);
                    for (int j = 0; j < left; j++) {
                        res -= pos.get(j);
                    }
                }
            }
            out.println(res);
        }

    }

    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.List;
import java.util.InputMismatchException;
import java.io.IOException;
import java.util.Collections;
import java.util.ArrayList;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author svilen.marchev@gmail.com
 */
public class Main {
  public static void main(String[] args) {
    InputStream inputStream = System.in;
    OutputStream outputStream = System.out;
    InputReader in = new InputReader(inputStream);
    PrintWriter out = new PrintWriter(outputStream);
    TaskF solver = new TaskF();
    solver.solve(1, in, out);
    out.close();
  }

  static class TaskF {
    int n;
    char[] s;
    int[] beauty;

    public void solve(int testNumber, InputReader in, PrintWriter out) {
      n = in.readInt();
      s = in.readString().toCharArray();
      beauty = new int[n];
      int totalBeauty = 0;
      for (int i = 0; i < n; ++i) {
        beauty[i] = in.readInt();
        totalBeauty += beauty[i];
      }

      // Find all pairs of indices (i, n-1-i) for which s[i]=s[n-1-i] and the most common char among those pairs.
      List<Integer> equalPairs = new ArrayList<>(n / 2);
      int[] charOccurrencesInEqualPairs = new int[128];
      char mostCommonCharInEqualPairs = 'a';
      for (int i = 0; i < n / 2; ++i) {
        if (s[i] == s[n - 1 - i]) {
          equalPairs.add(i);
          if (++charOccurrencesInEqualPairs[s[i]] > charOccurrencesInEqualPairs[mostCommonCharInEqualPairs]) {
            mostCommonCharInEqualPairs = s[i];
          }
        }
      }

      // These pairs must be broken up in any case, so account for them in the answer.
      int ans = totalBeauty;
      for (int equalPair : equalPairs) {
        ans -= Math.min(beauty[equalPair], beauty[n - 1 - equalPair]);
      }

      // If more than half of the pairs are with the same char, then we would not be able to reshuffle
      // the chars within the pairs, so we would need to break up some of the pairs with non-equal chars.
      // We would need to consider only pairs for which the chars are different AND neither of the two
      // chars is equal to the most common char in the "equal" pairs (otherwise swapping that char with
      // either of the chars in the "non-equal" pair would result in a non-palindromic pair).
      if (charOccurrencesInEqualPairs[mostCommonCharInEqualPairs] > equalPairs.size() / 2) {
        List<Integer> nonEqualPairsMinBeautyPenalties = new ArrayList<>(n / 2);
        for (int i = 0; i < n / 2; ++i) {
          if (s[i] != s[n - 1 - i] && s[i] != mostCommonCharInEqualPairs && s[n - 1 - i] != mostCommonCharInEqualPairs) {
            nonEqualPairsMinBeautyPenalties.add(Math.min(beauty[i], beauty[n - 1 - i]));
          }
        }
        Collections.sort(nonEqualPairsMinBeautyPenalties);
        int rem = 2 * charOccurrencesInEqualPairs[mostCommonCharInEqualPairs] - equalPairs.size();
        for (int i = 0; i < rem; ++i) {
          ans -= nonEqualPairsMinBeautyPenalties.get(i);
        }
      }

      out.println(ans);
    }

  }

  static class InputReader {
    private InputStream stream;
    private byte[] buf = new byte[1024];
    private int curChar;
    private int numChars;
    private InputReader.SpaceCharFilter filter;

    public InputReader(InputStream stream) {
      this.stream = stream;
    }

    public int read() {
      if (numChars == -1) {
        throw new InputMismatchException();
      }
      if (curChar >= numChars) {
        curChar = 0;
        try {
          numChars = stream.read(buf);
        } catch (IOException e) {
          throw new InputMismatchException();
        }
        if (numChars <= 0) {
          return -1;
        }
      }
      return buf[curChar++];
    }

    public int readInt() {
      int c = read();
      while (isSpaceChar(c)) {
        c = read();
      }
      int sgn = 1;
      if (c == '-') {
        sgn = -1;
        c = read();
      }
      int res = 0;
      do {
        if (c < '0' || c > '9') {
          throw new InputMismatchException();
        }
        res *= 10;
        res += c - '0';
        c = read();
      } while (!isSpaceChar(c));
      return res * sgn;
    }

    public String readString() {
      int c = read();
      while (isSpaceChar(c)) {
        c = read();
      }
      StringBuilder res = new StringBuilder();
      do {
        if (Character.isValidCodePoint(c)) {
          res.appendCodePoint(c);
        }
        c = read();
      } while (!isSpaceChar(c));
      return res.toString();
    }

    public boolean isSpaceChar(int c) {
      if (filter != null) {
        return filter.isSpaceChar(c);
      }
      return isWhitespace(c);
    }

    public static boolean isWhitespace(int c) {
      return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
    }

    public interface SpaceCharFilter {
      public boolean isSpaceChar(int ch);

    }

  }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Array;
import java.util.*;

/**
 * Created by nadya on 28/10/17.
 */
public class Educational {
    public static void main(String[] args) throws IOException {
        Educational c = new Educational();
        c.start();
    }

    private void start() throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer str = new StringTokenizer(in.readLine());
        int n = Integer.parseInt(str.nextToken());
        String s = in.readLine();
        int b[] = new int[n];
        TreeMap<Integer, Set<Integer>> w = new TreeMap<Integer, Set<Integer>>();

        str = new StringTokenizer(in.readLine());
        for (int i = 0; i < n; ++i) {
            b[i] = Integer.parseInt(str.nextToken());
        }
        char[] res = s.toCharArray();

        HashSet<Integer> waitingList = new HashSet<Integer>();
        for (int i = 0; i < n / 2; ++i) {
            if (res[i] == res[getvisavis(n, i)]) {
                if (waitingList.isEmpty()) {
                    waitingList.add(i);
                } else {
                    boolean found = false;
                    for (Integer j : waitingList) {
                        if (res[j] != res[i]) {
                            int minB1 = b[j] < b[getvisavis(n, j)] ? j : getvisavis(n, j);
                            int minB2 = b[i] < b[getvisavis(n, i)] ? i : getvisavis(n, i);
                            swap(res, minB1, minB2);
                            b[minB1] = 0;
                            b[minB2] = 0;
                            waitingList.remove(j);
                            found = true;
                            break;
                        }
                    }
                    if (! found) waitingList.add(i);
                }
            }
        }
        for (int i = 0; i < n / 2; ++i) {
            if (res[i] == res[getvisavis(n, i)]) {
               // System.out.println(res[i]);
            }
        }

        w.put(0, new HashSet<Integer>());
        for (int i = 0; i < n; ++i) {
          //  if (b[i] == 0) continue;
            if (!w.containsKey(b[i])) w.put(b[i], new HashSet<Integer>());
            w.get(b[i]).add(i);
        }

        for (int i = 0; i < n / 2; ++i) {
            if (res[i] == res[getvisavis(n, i)]) {

                boolean finished = false;

                int indexToChange = b[i] < b[getvisavis(n, i)] ? i : getvisavis(n, i);

                for (Map.Entry<Integer, Set<Integer>> l : w.entrySet()) {
                    Set<Integer> candidates = l.getValue();
                    for (Integer j : candidates) {
                        if (j == i || j == indexToChange || res[indexToChange] == res[j] || res[indexToChange] == res[getvisavis(n, j)]) {
                            continue;
                        }

                        swap(res, indexToChange, j);

                        b[j] = 0;
                        b[indexToChange] = 0;

                        w.get(0).add(j);
                        w.get(0).add(indexToChange);

                        w.get(b[indexToChange]).remove(indexToChange);
                        w.get(b[j]).remove(j);

                        finished = true;
                        break;
                    }

                    if (finished) break;
                }
                if (res[i] == res[getvisavis(n, i)]) System.out.println("alarma");
            }
        }
        for (int i = 0; i < n / 2; ++i) {
            if (res[i] == res[getvisavis(n, i)]) {
                System.out.println("FFFF");
            }
        }

        int sum = 0;
        for (int i = 0; i < n; ++i) {
            //if (!changed[i]) {
            sum += b[i];
            // }
        }

        System.out.println(sum);
    }

    public static int getvisavis(int n, int i) {
        return n - i - 1;
    }

    public static void swap(char[] a, int i, int j) {
        char t = a[i];
        a[i] = a[j];
        a[j] = t;
    }
}


// practice with rainboy
import java.io.*;
import java.util.*;

public class CF884F extends PrintWriter {
	CF884F() { super(System.out, true); }
	Scanner sc = new Scanner(System.in);
	public static void main(String[] $) {
		CF884F o = new CF884F(); o.main(); o.flush();
	}

	static final int A = 26, INF = 0x3f3f3f3f;
	int[] oo, oh; int __ = 1;
	int link(int o, int h) {
		oo[__] = o; oh[__] = h;
		return __++;
	}
	int[] ii, jj, cc, cost, cost_; int m_;
	int[] ae, pi, dd, ff; int n_;
	int[] pq, iq; int cnt;
	void init() {
		oo = new int[1 + m_ * 2]; oh = new int[1 + m_ * 2];
		ii = new int[m_]; jj = new int[m_]; cc = new int[m_ << 1];
		cost = new int[m_]; cost_ = new int[m_];
		pi = new int[n_]; dd = new int[n_]; ff = new int[n_];
		ae = new int[n_];
		pq = new int[1 + n_]; iq = new int[n_];
		m_ = 0;
	}
	void link_(int i, int j, int c, int co) {
		int h = m_++;
		ii[h] = i; jj[h] = j; cc[h << 1] = c;
		cost[h] = co;
		ae[i] = link(ae[i], h << 1);
		ae[j] = link(ae[j], h << 1 | 1);
	}
	boolean less(int u, int v) {
		return pi[u] < pi[v] || pi[u] == pi[v] && dd[u] < dd[v];
	}
	int i2(int i) {
		return (i *= 2) > cnt ? 0 : i < cnt && less(pq[i + 1], pq[i]) ? i + 1 : i;
	}
	void pq_up(int u) {
		int i, j, v;
		for (i = iq[u]; (j = i / 2) > 0 && less(u, v = pq[j]); i = j)
			pq[iq[v] = i] = v;
		pq[iq[u] = i] = u;
	}
	void pq_dn(int u) {
		int i, j, v;
		for (i = iq[u]; (j = i2(i)) > 0 && less(v = pq[j], u); i = j)
			pq[iq[v] = i] = v;
		pq[iq[u] = i] = u;
	}
	void pq_add_last(int u) {
		pq[iq[u] = ++cnt] = u;
	}
	int pq_remove_first() {
		int u = pq[1], v = pq[cnt--];
		if (v != u) {
			iq[v] = 1; pq_dn(v);
		}
		iq[u] = 0;
		return u;
	}
	boolean dijkstra(int s, int t) {
		Arrays.fill(pi, INF);
		pi[s] = 0; pq_add_last(s);
		while (cnt > 0) {
			int i = pq_remove_first();
			int d = dd[i] + 1;
			for (int o = ae[i]; o != 0; o = oo[o]) {
				int h_ = oh[o];
				if (cc[h_] > 0) {
					int h = h_ >> 1;
					int j = i ^ ii[h] ^ jj[h];
					int p = pi[i] + ((h_ & 1) == 0 ? cost_[h] : -cost_[h]);
					if (pi[j] > p || pi[j] == p && dd[j] > d) {
						if (pi[j] == INF)
							pq_add_last(j);
						pi[j] = p; dd[j] = d; ff[j] = h_;
						pq_up(j);
					}
				}
			}
		}
		return pi[t] != INF;
	}
	int trace(int s, int t) {
		while (t != s) {
			int h_ = ff[t], h = h_ >> 1;
			cc[h_]--; cc[h_ ^ 1]++;
			t ^= ii[h] ^ jj[h];
		}
		return 1;
	}
	int edmonds_karp(int s, int t) {
		for (int h = 0; h < m_; h++) {
			int i = ii[h], j = jj[h];
			pi[j] = Math.min(pi[j], pi[i] + cost[h]);
		}
		for (int h = 0; h < m_; h++) {
			int i = ii[h], j = jj[h];
			cost_[h] = cost[h] + pi[i] - pi[j];
		}
		int f = 0;
		while (dijkstra(s, t)) {
			f += trace(s, t);
			for (int h = 0; h < m_; h++) {
				int i = ii[h], j = jj[h];
				if (pi[i] != INF && pi[j] != INF) {
					// pi[j] <= pi[i] + cost_[h]
					// cost_[h] + pi[i] - pi[j] >= 0
					cost_[h] += pi[i] - pi[j];
				}
			}
		}
		int ans = 0;
		for (int h = 0; h < m_; h++)
			ans += cc[h << 1 | 1] * cost[h];
		return ans;
	}
	void main() {
		int n = sc.nextInt() / 2;
		n_ = 1 + n + A + 1;
		m_ = n + n * A + A;
		init();
		byte[] cc = sc.next().getBytes();
		int[] bb = new int[n * 2];
		for (int i = 0; i < n * 2; i++)
			bb[i] = sc.nextInt();
		for (int i = 0; i < n; i++)
			link_(0, 1 + i, 2, 0);
		for (int i = 0; i < n; i++) {
			int j = n * 2 - 1 - i;
			int ai = cc[i] - 'a';
			int aj = cc[j] - 'a';
			for (int a = 0; a < A; a++) {
				int b;
				if (a == ai && a == aj)
					b = Math.max(bb[i], bb[j]);
				else if (a == ai)
					b = bb[i];
				else if (a == aj)
					b = bb[j];
				else
					b = 0;
				link_(1 + i, 1 + n + a, 1, -b);
			}
		}
		int[] kk = new int[A];
		for (int i = 0; i < n * 2; i++) {
			int a = cc[i] - 'a';
			kk[a]++;
		}
		for (int a = 0; a < A; a++)
			link_(1 + n + a, n_ - 1, kk[a], 0);
		println(-edmonds_karp(0, n_ - 1));
	}
}


//package educational.round31;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.InputMismatchException;
import java.util.List;

public class F {
	InputStream is;
	PrintWriter out;
	String INPUT = "";

	void solve()
	{
		int n = ni();
		char[] s = ns(n);

		int[] f = new int[26];
		for(char c : s)f[c-'a']++;
		for(int i = 0;i < 26;i++){
			if(f[i] > n/2){
				out.println(-1);
				return;
			}
		}

		int[] a = na(n);
		for(int i = 0;i < n/2;i++){
			if(a[i] > a[n-1-i]){
				int d = a[i]; a[i] = a[n-1-i]; a[n-1-i] = d;
				char u = s[i]; s[i] = s[n-1-i]; s[n-1-i] = u;
			}
		}
		List<Edge> es = new ArrayList<>();
		int src = n, sink = n+1;
		for(int i = 0;i < n/2;i++){
			es.add(new Edge(src, i, 1, 0));
			es.add(new Edge(n-1-i, sink, 1, 0));
			for(int j = 0;j < n/2;j++){
				if(s[i] != s[n-1-j]){
					es.add(new Edge(i, n-1-j, 1, i == j ? 0 : a[i]));
				}
			}
		}
		long ans = Arrays.stream(a).sum();
		out.println(ans - solveMinCostFlow(compileWD(sink+1, es), src, sink, n));
	}

	public static class Edge
	{
		public int from, to;
		public int capacity;
		public int cost;
		public int flow;
		public Edge complement;
		// public int iniflow;

		public Edge(int from, int to, int capacity, int cost) {
			this.from = from;
			this.to = to;
			this.capacity = capacity;
			this.cost = cost;
		}
	}

	public static Edge[][] compileWD(int n, List<Edge> edges)
	{
		Edge[][] g = new Edge[n][];
		// cloning
		for(int i = edges.size()-1;i >= 0;i--){
			Edge origin = edges.get(i);
			Edge clone = new Edge(origin.to, origin.from, origin.capacity, -origin.cost);
			clone.flow = origin.capacity;
			clone.complement = origin;
			origin.complement = clone;
			edges.add(clone);
		}

		int[] p = new int[n];
		for(Edge e : edges)p[e.from]++;
		for(int i = 0;i < n;i++)g[i] = new Edge[p[i]];
		for(Edge e : edges)g[e.from][--p[e.from]] = e;
		return g;
	}

	// NOT VERIFIED
	public static Edge[][] compileWU(int n, List<Edge> edges)
	{
		Edge[][] g = new Edge[n][];
		// cloning
		for(int i = edges.size()-1;i >= 0;i--){
			Edge origin = edges.get(i);
			Edge back = new Edge(origin.to, origin.from, origin.capacity, origin.cost);
			edges.add(back);
		}
		for(int i = edges.size()-1;i >= 0;i--){
			Edge origin = edges.get(i);
			Edge clone = new Edge(origin.to, origin.from, origin.capacity, -origin.cost);
			clone.flow = origin.capacity;
			clone.complement = origin;
			origin.complement = clone;
			edges.add(clone);
		}

		int[] p = new int[n];
		for(Edge e : edges)p[e.from]++;
		for(int i = 0;i < n;i++)g[i] = new Edge[p[i]];
		for(Edge e : edges)g[e.from][--p[e.from]] = e;
		return g;
	}

	public static long solveMinCostFlow(Edge[][] g, int source, int sink, long all)
	{
		int n = g.length;
		long mincost = 0;
		int[] potential = new int[n];

		final int[] d = new int[n];
		MinHeap q = new MinHeap(n);
		while(all > 0){
			// shortest path src->sink
			Edge[] inedge = new Edge[n];
			Arrays.fill(d, Integer.MAX_VALUE / 2);
			d[source] = 0;
			q.add(source, 0);
			while(q.size() > 0){
				int cur = q.argmin();
				q.remove(cur);
				for(Edge ne : g[cur]){
					if(ne.capacity - ne.flow > 0){
						int nd = d[cur] + ne.cost + potential[cur] - potential[ne.to];
						if(d[ne.to] > nd){
							inedge[ne.to] = ne;
							d[ne.to] = nd;
							q.update(ne.to, nd);
						}
					}
				}
			}

			if(inedge[sink] == null)break;

			long minflow = all;
			long sumcost = 0;
			for(Edge e = inedge[sink];e != null;e = inedge[e.from]){
				if(e.capacity - e.flow < minflow)minflow = e.capacity - e.flow;
				sumcost += e.cost;
			}
			mincost += minflow * sumcost;
			for(Edge e = inedge[sink];e != null;e = inedge[e.from]){
				e.flow += minflow;
				e.complement.flow -= minflow;
			}

			all -= minflow;
			for(int i = 0;i < n;i++){
				potential[i] += d[i];
			}
		}
		return mincost;
	}

	public static class MinHeap {
		public int[] a;
		public int[] map;
		public int[] imap;
		public int n;
		public int pos;
		public static int INF = Integer.MAX_VALUE;

		public MinHeap(int m)
		{
			n = m+2;
			a = new int[n];
			map = new int[n];
			imap = new int[n];
			Arrays.fill(a, INF);
			Arrays.fill(map, -1);
			Arrays.fill(imap, -1);
			pos = 1;
		}

		public int add(int ind, int x)
		{
			int ret = imap[ind];
			if(imap[ind] < 0){
				a[pos] = x; map[pos] = ind; imap[ind] = pos;
				pos++;
				up(pos-1);
			}
			return ret != -1 ? a[ret] : x;
		}

		public int update(int ind, int x)
		{
			int ret = imap[ind];
			if(imap[ind] < 0){
				a[pos] = x; map[pos] = ind; imap[ind] = pos;
				pos++;
				up(pos-1);
			}else{
				int o = a[ret];
				a[ret] = x;
				up(ret);
				down(ret);
//				if(a[ret] > o){
//					up(ret);
//				}else{
//					down(ret);
//				}
			}
			return x;
		}

		public int remove(int ind)
		{
			if(pos == 1)return INF;
			if(imap[ind] == -1)return INF;

			pos--;
			int rem = imap[ind];
			int ret = a[rem];
			map[rem] = map[pos];
			imap[map[pos]] = rem;
			imap[ind] = -1;
			a[rem] = a[pos];
			a[pos] = INF;
			map[pos] = -1;

			up(rem);
			down(rem);
			return ret;
		}

		public int min() { return a[1]; }
		public int argmin() { return map[1]; }
		public int size() {	return pos-1; }

		private void up(int cur)
		{
			for(int c = cur, p = c>>>1;p >= 1 && a[p] > a[c];c>>>=1, p>>>=1){
				int d = a[p]; a[p] = a[c]; a[c] = d;
				int e = imap[map[p]]; imap[map[p]] = imap[map[c]]; imap[map[c]] = e;
				e = map[p]; map[p] = map[c]; map[c] = e;
			}
		}

		private void down(int cur)
		{
			for(int c = cur;2*c < pos;){
				int b = a[2*c] < a[2*c+1] ? 2*c : 2*c+1;
				if(a[b] < a[c]){
					int d = a[c]; a[c] = a[b]; a[b] = d;
					int e = imap[map[c]]; imap[map[c]] = imap[map[b]]; imap[map[b]] = e;
					e = map[c]; map[c] = map[b]; map[b] = e;
					c = b;
				}else{
					break;
				}
			}
		}
	}

	void run() throws Exception
	{
		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		tr(System.currentTimeMillis()-s+"ms");
	}

	public static void main(String[] args) throws Exception { new F().run(); }

	private byte[] inbuf = new byte[1024];
	public int lenbuf = 0, ptrbuf = 0;

	private int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf){
			ptrbuf = 0;
			try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
	private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

	private double nd() { return Double.parseDouble(ns()); }
	private char nc() { return (char)skip(); }

	private String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b))){
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private char[][] nm(int n, int m)
	{
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}

	private int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}

	private int ni()
	{
		int num = 0, b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	private void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}


import java.io.IOException;
import java.util.*;
import java.io.*;
public class ll {
    public static void main(String[] args) throws IOException {
        gg g = new gg();
    }

}
class gg {
    gg() throws IOException {
        FScanner fs = new FScanner(new InputStreamReader(System.in));
        PrintWriter pw = new PrintWriter(System.out);
        int n = fs.nextInt();
        char[] word = fs.nextLine().toCharArray();
        int[] vals = fs.iarr(n);
        int[] badones = new int[26];
        int m = 0;
        for (int i = 0; i<n/2; i++)
            if (word[i] == word[n-i-1])
            {
                badones[word[i]-'a']++;
                m++;
            }
        int max = 0;
        boolean bad = false;
        int val = -1;
        for (int i  = 0; i<26; i++)
            if (badones[i]*2>m)
            {
                bad = true;
                val = i;
            }
        if (!bad) {
            long sum = 0;
            for (int i = 0; i<n/2; i++)
                if (word[i] !=word[n-i-1])
                    sum+=vals[i]+vals[n-i-1];
                else sum+=Math.max(vals[i], vals[n-i-1]);
            pw.println(sum);
        } else {
            int others = badones[val]-(m-badones[val]);
            ArrayList<Integer> appr = new ArrayList<>();
            for (int i = 0; i<n/2; i++)
                if (word[i] != word[n-i-1] && word[i] != 'a'+val && word[n-i-1] != 'a'+val)
                    appr.add(Math.min(vals[i], vals[n-i-1]));
            appr.sort(null);
            long ans = 0;
            for (int i =0 ; i<n/2; i++) {
                if (word[i] == word[n-i-1])
                    ans+=Math.max(vals[i], vals[n-i-1]);
                else ans+=vals[i]+vals[n-i-1];
            }
            for (int i =0 ; i<others; i++)
                ans-=appr.get(i);
            pw.println(ans);
        }
        pw.close();
    }

    void add(long s, TreeMap<Long, Integer> map) {
        if (map.containsKey(s))
            map.put(s, map.get(s)+1);
        else map.put(s, 1);
    }
    long lowest(TreeMap<Long, Integer> map) {
        if (map.size() == 0)
            return -1;
        long v = map.firstKey();
        if (map.get(v) == 1) {
            map.remove(v);
        } else {
            map.put(v, map.get(v)-1);
        }
        return v;
    }

}

class FScanner {
    StringTokenizer st;
    BufferedReader reader;
    FScanner(InputStreamReader isr) throws IOException {
        reader = new BufferedReader(isr);
    }

    String nextLine() throws IOException {
        return reader.readLine();
    }

    String nextToken() throws IOException{
        while (st == null || !st.hasMoreTokens()) {
            String s = reader.readLine();
            if (s == null)
                return null;
            st = new StringTokenizer(s);
        }
        return st.nextToken();
    }

    int nextInt() throws IOException {
        return Integer.parseInt(nextToken());
    }

    double nextDouble() throws IOException {
        return Double.parseDouble(nextToken());
    }

    char nextChar() throws IOException {
        return (char) reader.read();
    }

    long nextLong() throws IOException {
        return Long.parseLong(nextToken());
    }

    int[] iarr(int n) throws IOException {
        int[] mas = new int[n];
        for (int i =0 ; i<n; i++)
            mas[i] = nextInt();
        return mas;
    }

    double[] darr(int n) throws IOException {
        double[] mas = new double[n];
        for (int i =0 ; i<n; i++)
            mas[i] = nextDouble();
        return mas;
    }

    char[][] cmas2 (int n, int m) throws IOException {
        char[][] mas = new char[n][m];
        for (int i =0 ; i<n; i++)
            mas[i] = nextLine().toCharArray();
        return mas;
    }

    long[] larr(int n) throws IOException {
        long[] mas = new long[n];
        for (int i =0 ; i<n; i++)
            mas[i] = nextLong();
        return mas;
    }

}


import java.io.*;
import java.util.*;

public class MinCostMaxFlow {
    public static void main(String[] args) {
        InputReader in = new InputReader();
        OutputWriter out = new OutputWriter(System.out);
		int letters = 'z' - 'a' + 1;
        int n = in.nextInt();
        String s = in.next();
        char[] string = s.toCharArray();
        int[] letCount = new int[letters];
        for(int i = 0; i < n; ++i) {
            letCount[string[i] - 'a']++;
        }
        int[] b = new int[n];
        for(int i = 0; i < n; ++i) {
            b[i] = in.nextInt();
        }

        int source = 0;
        int charOffSet = 1;
        int pairOffSet = charOffSet + letters;
        int sinkOffSet = pairOffSet + n / 2;
        int sink = sinkOffSet;
        int vNum = sinkOffSet + 1;

        Graph g = new Graph(vNum, source, sink);
        //Source -> Letters -> Pairs
        for(int i = 0; i < letters; ++i) {
            g.addEdge(source, charOffSet + i, letCount[i], 0);
            for(int j = 0; j < n/2; ++j) {
                char c1 = string[j];
                char c2 = string[n - j - 1];
                if(c1 == 'a' + i) {
                    if(c1 == c2) {
                        g.addEdge(charOffSet + i, pairOffSet + j,
                            1, -Integer.max(b[j], b[n - j - 1]));
                    } else {
                        g.addEdge(charOffSet + i, pairOffSet + j, 1, -b[j]);
                    }
                } else {
                    if(c2 == 'a' + i) {
                        g.addEdge(charOffSet + i, pairOffSet + j, 1, -b[n - j - 1]);
                    } else {
                        g.addEdge(charOffSet + i, pairOffSet + j, 1, 0);
                    }
                }
            }
        }
        //Pairs -> Sink
        for(int i = 0; i < n/2; ++i) {
            g.addEdge(pairOffSet + i, sink, 2, 0);
        }

        int[] ans = g.getMinCostMaxFlow();
//		System.out.println("flow: " + ans[0]);
//		System.out.println("cost: " + -ans[1]);
        System.out.println(-ans[1]);
    }

    public static class OutputWriter {
        private final PrintWriter writer;

        public OutputWriter(OutputStream outputStream) {
            writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
        }

        public OutputWriter(Writer writer) {
            this.writer = new PrintWriter(writer);
        }

        public void print(Object... objects) {
            for (int i = 0; i < objects.length; i++) {
                if (i != 0) {
                    writer.print(' ');
                }
                writer.print(objects[i]);
            }
        }

        public void println(Object... objects) {
            print(objects);
            writer.println();
        }

        public void printf(String format, Object... objects) {
            writer.printf(format, objects);
        }

        public void close() {
            writer.close();
        }

        public void flush() {
            writer.flush();
        }

    }

    static class InputReader
    {
        BufferedReader br;
        StringTokenizer st;

        public InputReader()
        {
            br = new BufferedReader(new
                     InputStreamReader(System.in));
        }

        String next()
        {
            while (st == null || !st.hasMoreElements())
            {
                try
                {
                    st = new StringTokenizer(br.readLine());
                }
                catch (IOException  e)
                {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt()
        {
            return Integer.parseInt(next());
        }

        long nextLong()
        {
            return Long.parseLong(next());
        }

        double nextDouble()
        {
            return Double.parseDouble(next());
        }

        String nextLine()
        {
            String str = "";
            try
            {
                str = br.readLine();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            return str;
        }
    }
}

class Graph {
    private int vNum;
    private int src;
    private int sink;

    private int[][] res;
    private int[][] cost;
    private List<Edge> costGraph;
    private int[] p;
    private int[] d;

    private static class Edge {
      final int from;
      final int to;
      final int cost;

      Edge(int from, int to, int cost) {
          this.from = from;
          this.to = to;
          this.cost = cost;
      }
  }

    public int getVertexNumber() {
        return vNum;
    }

    public Graph(int vNum, int src, int sink) {
        this.vNum = vNum;
        this.src = src;
        this.sink = sink;
        res = new int[vNum][vNum];
        cost = new int[vNum][vNum];
        costGraph = new ArrayList<>();
        d = new int[vNum];
        p = new int[vNum];
    }

    public void addEdge(int from, int to, int capacity, int cost) {
        res[from][to] += capacity;
        this.cost[from][to] = cost;
        this.cost[to][from] = -cost;

    }

    private boolean findCheapestPath() {
    	costGraph.clear();
    	for(int i = 0; i < vNum; ++i) {
    		for(int j = 0; j < vNum; ++j) {
    			if(res[i][j] > 0) {
    				costGraph.add(new Edge(i, j, cost[i][j]));
    			}
    		}
    	}

    	Arrays.fill(d, Integer.MAX_VALUE);
    	Arrays.fill(p, -1);

    	d[src] = 0;

    	boolean changed = false;
    	for(int i = 0; i < vNum - 1; ++i) {
    		for(Edge e: costGraph) {
    			// Be careful here
    			// Overfloating can be
    			if(d[e.from] != Integer.MAX_VALUE && d[e.from] + e.cost < d[e.to]) {
    				d[e.to] = d[e.from] + e.cost;
    				p[e.to] = e.from;
    				changed = true;
    			}
    		}
    		if(!changed) {
    			break;
    		}
    	}

    	return p[sink] != -1;
    }

    private int[] augmentPath(int from, int to, int flow) {
    	int pathCost = 0;
    	for(int cur = to; cur != from; cur = p[cur]) {
    		flow = Integer.min(flow, res[p[cur]][cur]);
    	}
    	for(; to != from; to = p[to]) {
    		res[p[to]][to] -= flow;
    		res[to][p[to]] += flow;
    		pathCost += cost[p[to]][to] * flow;
    	}
    	return new int[] {flow, pathCost};
    }

    public int[] getMinCostMaxFlow() {
    	int flow = 0;
    	int totalCost = 0;
    	while(findCheapestPath()) {
    		int[] result = augmentPath(src, sink, Integer.MAX_VALUE);
    		flow += result[0];
    		totalCost += result[1];
    	}
    	return new int[] {flow, totalCost};
    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.util.InputMismatchException;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        OutputWriter out = new OutputWriter(outputStream);
        TaskF solver = new TaskF();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskF {
        static boolean debug = false;
        int numberNumber;
        int t;
        long[][] bin = IntegerUtils.generateBinomialCoefficients(100);

        static {
            if (debug) {
                try {
                    FileOutputStream f = new FileOutputStream("file.txt");
                    System.setErr(new PrintStream(f));
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }
            }
        }

        public void solve(int testNumber, InputReader in, OutputWriter out) {
            numberNumber = in.readInt();
            t = in.readInt();

//        t = 1;

            //        HashMap<Integer, String> answers = new HashMap<>();
//
//        for (int i = 1, cnt = 0; cnt < 1e5; i++) {
//            int[] cntTake = new int[16];
//            for (char c : String.format("%x", i).toCharArray()) {
//                ++cntTake[Integer.parseInt("" + c, 16)];
//            }
//            boolean ok = true;
//            for (int c : cntTake) {
//                ok &= c <= t;
//            }
//            if (ok) {
//                ++cnt;
//                String answer = String.format("%x", i);
//                answers.put(cnt, answer);
//                System.err.println(cnt + " = " + answer);
//                System.err.flush();
//            }
//        }

//
//        for (int _numberNumber = 1; ; _numberNumber++) {
//            numberNumber = _numberNumber;
            int wordLength = 1;
            for (; ; wordLength++) {
                long[][] dp = new long[16][wordLength + 1];

                for (int length = 0; length <= wordLength; length++) {
                    for (int ch = 0; ch < 16; ch++) {
                        if (length == 0) {
                            dp[ch][length] = 1;
                        } else if (ch == 0) {
                            if (length <= t) {
                                dp[ch][length] = bin[wordLength - 1][length];
                            }
                        } else {
                            dp[ch][length] += dp[ch - 1][length];
                            for (int c = 1; c <= Math.min(length, t); c++) {
                                dp[ch][length] += bin[wordLength - length + c][c] * dp[ch - 1][length - c];
                            }
                        }
                    }
                }

                System.err.println("wordLength, dp: " + wordLength + " " + dp[15][wordLength]);
                System.err.flush();
                if (dp[15][wordLength] < numberNumber) {
                    numberNumber -= dp[15][wordLength];
                } else {
//                out.printLine("wordLength: " + wordLength);
                    break;
                }
            }

            StringBuilder ans = new StringBuilder();
            int[] maxCnt = new int[16];
            Arrays.fill(maxCnt, t);
            for (int pos = 0; pos < wordLength; pos++) {
                boolean addCh = false;
                for (int ch = 0; ch < 16; ch++) {
                    if (pos == 0 && ch == 0) {
                        continue;
                    }
                    if (maxCnt[ch] == 0) {
                        continue;
                    }
                    --maxCnt[ch];
                    long dp = getDp(wordLength - pos - 1, maxCnt);
                    if (numberNumber <= dp) {
                        ans.append(String.format("%x", ch));
                        addCh = true;
                        break;
                    } else {
                        ++maxCnt[ch];
                        numberNumber -= dp;
                    }
                }
                if (!addCh) {
                    throw new RuntimeException("no addCh");
//                    out.printLine("no add ch at pos=" + pos, "   : ", _numberNumber, answers.get(_numberNumber), ans);
//                    return;
                }
            }
//            if (!answers.get(_numberNumber).equals(ans.toString())) {
//                out.printLine("FUCK:", _numberNumber, answers.get(_numberNumber), ans);
//                return;
//            }
            out.printLine(ans);
//        }
        }

        private long getDp(int wordLength, int[] maxCnt) {
            long[][] dp = new long[16][wordLength + 1];
            for (int length = 0; length <= wordLength; length++) {
                for (int ch = 0; ch < 16; ch++) {
                    if (length == 0) {
                        dp[ch][length] = 1;
                    } else {
                        if (ch != 0) {
                            dp[ch][length] += dp[ch - 1][length];
                        }
                        for (int cnt = 1; cnt <= Math.min(length, maxCnt[ch]); cnt++) {
                            if (ch == 0) {
                                if (length == cnt) {
                                    dp[ch][length] += bin[wordLength][cnt];
                                }
                            } else {
                                dp[ch][length] += bin[wordLength - length + cnt][cnt] * dp[ch - 1][length - cnt];
                            }
                        }
                    }
                }
            }
            return dp[15][wordLength];
        }

    }

    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
        private InputReader.SpaceCharFilter filter;

        public InputReader(InputStream stream) {
            this.stream = stream;
        }

        public int read() {
            if (numChars == -1) {
                throw new InputMismatchException();
            }
            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (numChars <= 0) {
                    return -1;
                }
            }
            return buf[curChar++];
        }

        public int readInt() {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
            }
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            int res = 0;
            do {
                if ((c < '0') || (c > '9')) {
                    throw new InputMismatchException();
                }
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public boolean isSpaceChar(int c) {
            if (filter != null) {
                return filter.isSpaceChar(c);
            }
            return isWhitespace(c);
        }

        public static boolean isWhitespace(int c) {
            return (c == ' ') || (c == '\n') || (c == '\r') || (c == '\t') || (c == -1);
        }

        public interface SpaceCharFilter {
            public boolean isSpaceChar(int ch);

        }

    }

    static class IntegerUtils {
        public static long[][] generateBinomialCoefficients(int n) {
            long[][] result = new long[n + 1][n + 1];
            for (int i = 0; i <= n; i++) {
                result[i][0] = 1;
                for (int j = 1; j <= i; j++) {
                    result[i][j] = result[i - 1][j - 1] + result[i - 1][j];
                }
            }
            return result;
        }

    }

    static class OutputWriter {
        private final PrintWriter writer;

        public OutputWriter(OutputStream outputStream) {
            writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
        }

        public OutputWriter(Writer writer) {
            this.writer = new PrintWriter(writer);
        }

        public void print(Object... objects) {
            for (int i = 0; i < objects.length; i++) {
                if (i != 0) {
                    writer.print(' ');
                }
                writer.print(objects[i]);
            }
        }

        public void printLine(Object... objects) {
            print(objects);
            writer.println();
        }

        public void close() {
            writer.close();
        }

    }
}


import java.io.*;
import java.util.*;

public class Main implements Runnable{
    public static void main(String[] args){
        //new Thread(null,new Main(),"Thread-1",1024*1024*10).start();
        new Main().run();
    }
    int mod=1000000007;
    int n,k,m;
    private void solve() throws Exception {
        InputReader in = new InputReader(System.in);
        PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
        n=in.nextInt();k=in.nextInt();m=in.nextInt();
        int[][]ma=new int[(k+1)*(1<<m)][(k+1)*(1<<m)];
        for(int i=0;i<=k;i++) {
            for (int j = 0; j < (1 << m); j++) {
                ma[trans(i,j>>1)][trans(i,j)]=1;
                if(i<k)ma[trans(i+1,j>>1|(1<<m-1))][trans(i,j)]=Integer.bitCount(j)+1;
            }
        }
        ma=FastPowMod(ma,n);
        long ans=0;
        for(int i=trans(k,0);i<ma.length;i++)ans+=ma[i][0];
        out.println(ans%mod);
        out.flush();
    }
    public int[][] FastPowMod(int[][] a,int b){
        int[][] ans=new int[a.length][a.length];
        for(int i=0;i<a.length;i++)ans[i][i]=1;
        while(b>0){
            if((b&1)==1)
                ans=modMul(ans,a);
            a=modMul(a,a);
            b>>=1;
        }
        return ans;
    }
    public int[][] modMul(int[][]a,int[][]b){
        int row=a.length,column=b[0].length;
        int len=b.length;
        int[][] ans=new int[row][column];
        for(int i=0;i<row;i++){
            for(int j=0;j<len;j++){
                //if(a[i][j]==0)continue;//稀疏矩阵优化
                for(int k=0;k<column;k++){
                    ans[i][k]+=(long)a[i][j]*b[j][k]%mod;
                    ans[i][k]%=mod;
                }
            }
        }
        return ans;
    }

    int trans(int x,int y){
        return x*(1<<m)+y;
    }
    @Override
    public void run() {
        try {
            solve();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    void shuffle(int[]a,int l,int r){
        Random rnd=new Random();
        for (int i=r; i>l+1; i--) {
            int j=rnd.nextInt(i),tmp=a[j];
            a[j]=a[i-1];
            a[i-1]=tmp;
        }
    }
    void shuffle(Object[]a,int l,int r){
        Random rnd=new Random();
        for (int i=r; i>l+1; i--) {
            int j=rnd.nextInt(i);
            Object tmp=a[j];
            a[j]=a[i-1];
            a[i-1]=tmp;
        }
    }
    void shuffle(long[]a,int l,int r){
        Random rnd=new Random();
        for (int i=r; i>l+1; i--) {
            int j=rnd.nextInt(i);
            long tmp=a[j];
            a[j]=a[i-1];
            a[i-1]=tmp;
        }
    }
    class InputReader{
        StreamTokenizer tokenizer;
        public InputReader(InputStream stream){
            tokenizer=new StreamTokenizer(new BufferedReader(new InputStreamReader(stream)));
            tokenizer.ordinaryChars(33,126);
            tokenizer.wordChars(33,126);
        }
        public String next() throws IOException {
            tokenizer.nextToken();
            return tokenizer.sval;
        }
        public int nextInt() throws IOException {
            return Integer.parseInt(next());
        }
        public long nextLong() throws IOException {
            return Long.parseLong(next());
        }
        public boolean hasNext() throws IOException {
            int res=tokenizer.nextToken();
            tokenizer.pushBack();
            return res!=tokenizer.TT_EOF;
        }
    }
}


import java.io.*;
import java.util.*;

public class Main implements Runnable{
    public static void main(String[] args){
        //new Thread(null,new Main(),"Thread-1",1024*1024*10).start();
        new Main().run();
    }
    int mod=1000000007;
    int n,k,m;
    private void solve() throws Exception {
        InputReader in = new InputReader(System.in);
        PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
        n=in.nextInt();k=in.nextInt();m=in.nextInt();
        int[][]ma=new int[(k+1)*(1<<m)][(k+1)*(1<<m)];
        for(int i=0;i<=k;i++) {
            for (int j = 0; j < (1 << m); j++) {
                ma[trans(i,j>>1)][trans(i,j)]=1;
                if(i<k)ma[trans(i+1,j>>1|(1<<m-1))][trans(i,j)]=Integer.bitCount(j)+1;
            }
        }
        ma=FastPowMod(ma,n);
        long ans=0;
        for(int i=trans(k,0);i<ma.length;i++)ans+=ma[i][0];
        out.println(ans%mod);
        out.flush();
    }
    public int[][] FastPowMod(int[][] a,int b){
        int[][] ans=new int[a.length][a.length];
        for(int i=0;i<a.length;i++)ans[i][i]=1;
        while(b>0){
            if((b&1)==1)
                ans=modMul(ans,a);
            a=modMul(a,a);
            b>>=1;
        }
        return ans;
    }
    public int[][] modMul(int[][]a,int[][]b){
        int row=a.length,column=b[0].length;
        int len=b.length;
        int[][] ans=new int[row][column];
        for(int i=0;i<row;i++){
            for(int j=0;j<len;j++){
                if(a[i][j]==0)continue;//稀疏矩阵优化
                for(int k=0;k<column;k++){
                    ans[i][k]+=(long)a[i][j]*b[j][k]%mod;
                    ans[i][k]%=mod;
                }
            }
        }
        return ans;
    }

    int trans(int x,int y){
        return x*(1<<m)+y;
    }
    @Override
    public void run() {
        try {
            solve();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    void shuffle(int[]a,int l,int r){
        Random rnd=new Random();
        for (int i=r; i>l+1; i--) {
            int j=rnd.nextInt(i),tmp=a[j];
            a[j]=a[i-1];
            a[i-1]=tmp;
        }
    }
    void shuffle(Object[]a,int l,int r){
        Random rnd=new Random();
        for (int i=r; i>l+1; i--) {
            int j=rnd.nextInt(i);
            Object tmp=a[j];
            a[j]=a[i-1];
            a[i-1]=tmp;
        }
    }
    void shuffle(long[]a,int l,int r){
        Random rnd=new Random();
        for (int i=r; i>l+1; i--) {
            int j=rnd.nextInt(i);
            long tmp=a[j];
            a[j]=a[i-1];
            a[i-1]=tmp;
        }
    }
    class InputReader{
        StreamTokenizer tokenizer;
        public InputReader(InputStream stream){
            tokenizer=new StreamTokenizer(new BufferedReader(new InputStreamReader(stream)));
            tokenizer.ordinaryChars(33,126);
            tokenizer.wordChars(33,126);
        }
        public String next() throws IOException {
            tokenizer.nextToken();
            return tokenizer.sval;
        }
        public int nextInt() throws IOException {
            return Integer.parseInt(next());
        }
        public long nextLong() throws IOException {
            return Long.parseLong(next());
        }
        public boolean hasNext() throws IOException {
            int res=tokenizer.nextToken();
            tokenizer.pushBack();
            return res!=tokenizer.TT_EOF;
        }
    }
}


import java.io.*;
import java.util.*;

public class Ada extends PrintWriter {
    Ada() { super(System.out, true); }
    Scanner sc = new Scanner(System.in);
    public static void main(String[] $) {
        Ada o = new Ada(); o.main(); o.flush();
    }

    int compress(int[] aa, int n) {
        Random rand = new Random();
        for (int i = 0; i < n; i++) {
            int j = rand.nextInt(i + 1);
            int tmp = aa[i]; aa[i] = aa[j]; aa[j] = tmp;
        }
        Arrays.sort(aa, 0, n);
        int m = 1;
        for (int i = 1; i < n; i++)
            if (aa[i] != aa[i - 1])
                aa[m++] = aa[i];
        return m;
    }
    void main() {
        int a = sc.nextInt();
        int b = sc.nextInt();
        int n = a + b;
        int s = (int) Math.sqrt(n) + 1;
        int[] gg = new int[s + s];
        int m = 0;
        for (int g = 1; g <= s; g++)
            gg[m++] = g;
        for (int k = 1; k <= s; k++) {
            int g = n / k;
	    gg[m++] = g;
        }
        m = compress(gg, m);
        int ans = 0;
        for (int h = 0; h < m; h++) {
            int g = gg[h];
            int al = (int) ((a + (long) g) / (g + 1));
            int bl = (int) ((b + (long) g) / (g + 1));
            int ar = a / g;
            int br = b / g;
            if (al <= ar && bl <= br) {
                int l = Math.max(n / (g + 1) + 1, al + bl);
                int r = Math.min(n / g, ar + br);
                if (l <= r)
                    ans += r - l + 1;
            }
        }
        println(ans);
    }
}


import java.util.*;

/**
 * Created by zhengyanglzy on 2017/6/24.
 */
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (sc.hasNext()) {
            long houseNum = sc.nextLong();
            long k = sc.nextLong();
            System.out.println(cal(houseNum, k));
        }
    }

    static long cal(long houseNum, long k) {
        if (k == 1) {
            return 1;

        } else if (k == 2) {
            return houseNum;
        }
        return 1 + findLabel(houseNum - 2, k - 2);
    }

    static long findLabel(long houseNum, long k) {
        // System.out.printf("%d %d\n", houseNum, k);
        long medium = (houseNum + 1) / 2;
        if (k == 1) {
            return medium;
        }
        k -= 1;
        Part leftPart = new Part(medium - 1);
        Part rightPart = new Part(houseNum - medium);
        long leftTotal = 0;
        long rightTotal = 0;
        while (true) {
            long left = leftPart.peek();
            long right = rightPart.peek();
            if (left == 0 && right == 0) {
                break;
            }
            if (k > left + right) {
                k -= left + right;
                leftTotal += left;
                rightTotal += right;
                leftPart.split();
                rightPart.split();
                continue;
            }
            leftPart.collapse();
            rightPart.collapse();
            TreeSet<Long> set = new TreeSet<Long>();
            set.addAll(leftPart.segs.keySet());
            set.addAll(rightPart.segs.keySet());
            for (long len : set.descendingSet()) {
                if (leftPart.segs.containsKey(len)) {
                    if (leftPart.segs.get(len) >= k) {
                        return findLabel(medium - 1, leftTotal + k);
                    } else {
                        k -= leftPart.segs.get(len);
                        leftTotal += leftPart.segs.get(len);
                    }
                }
                if (rightPart.segs.containsKey(len)) {
                    if (rightPart.segs.get(len) >= k) {
                        return medium + findLabel(houseNum - medium, rightTotal + k);
                    } else {
                        k -= rightPart.segs.get(len);
                        rightTotal += rightPart.segs.get(len);
                    }
                }
            }
        }
        // 只剩1和2
        if (medium - 1 - leftTotal >= k) {
            return findLabel(medium - 1, leftTotal + k);
        }
        return medium + findLabel(houseNum - medium, rightTotal + k - (medium - 1 - leftTotal));
    }

    static class Part {
        Map<Long, Long> segs;

        Part(long num) {
            segs = new HashMap<Long, Long>();
            segs.put(num, 1L);
        }

        void split() {
            Map<Long, Long> newMap = new HashMap<Long, Long>();
            for (Map.Entry<Long, Long> entry : segs.entrySet()) {
                if (entry.getKey() <= 2) {
                    update(newMap, entry.getKey(), entry.getValue());
                    continue;
                }
                long medium = (entry.getKey() + 1) / 2;
                update(newMap, medium - 1, entry.getValue());
                update(newMap, entry.getKey() - medium, entry.getValue());
            }
            segs = newMap;
        }

        long peek() {
            long ret = 0;
            for (Map.Entry<Long, Long> entry : segs.entrySet()) {
                if (entry.getKey() > 2) {
                    ret += entry.getValue();
                }
            }
            return ret;
        }

        void collapse() {
            Map<Long, Long> newMap = new HashMap<Long, Long>();
            for (Map.Entry<Long, Long> entry : segs.entrySet()) {
                update(newMap, (entry.getKey() + 1) / 2, entry.getValue());
            }
            segs = newMap;
        }

        static void update(Map<Long, Long> map, long key, long inc) {
            if (!map.containsKey(key)) {
                map.put(key, 0L);
            }
            map.put(key, map.get(key) + inc);
        }
    }

    static class Seg implements Comparable<Seg> {
        int start;
        int length;

        public Seg(int start, int length) {
            this.start = start;
            this.length = length;
        }

        public int compareTo(Seg o) {
            int diff = (length - 1) / 2 - (o.length -1) / 2;
            if (diff != 0) {
                return -diff;
            }
            return start - o.start;
        }
    }
}