//package round418;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

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

	void solve()
	{
		int mod = 1000000007;
		int n = ni();
		int[] ds = na(n);

		long[][] C = new long[50 + 1][50 + 1];
		for (int i = 0; i <= 50; i++) {
			C[i][0] = 1;
			for (int j = 1; j <= i; j++) {
				C[i][j] = C[i - 1][j - 1] + C[i - 1][j];
				if (C[i][j] >= mod)
					C[i][j] -= mod;
			}
		}

		long[] ip2 = new long[50];
		long i2 = invl(2, mod);
		ip2[0] = 1;
		for(int i = 1;i < 50;i++)ip2[i] = ip2[i-1] * i2 % mod;

		// [同層で処理済みの1次の頂点][同層で処理済みの2次の頂点][同層で未処理の頂点]
		long[][][] dp = new long[30][30][30];
		dp[0][0][ds[0]] = ds[0] == 3 ? invl(6, mod) : invl(2, mod);
		for(int i = 1;i < n;i++){
			long[][][] ndp = new long[30][30][30];
			for(int k = 0;k < 30;k++){
				for(int l = 0;k+l < 30;l++){
					for(int m = 1;k+l+m < 30;m++){
						if(dp[k][l][m] == 0)continue;
						// 未処理の点から1個選ぶ
						// 1,2次の頂点と結ぶ
						for(int c1 = 0;c1 <= k && c1 <= ds[i]-1;c1++){
							for(int c2 = 0;c2 <= l && c1+c2 <= ds[i]-1;c2++){
								int n1 = k-c1+c2, n2 = l-c2;
								int pl = ds[i] - 1 - c1 - c2;
								if(pl == 1)n1++;
								if(pl == 2)n2++;
								long v = m * dp[k][l][m] % mod * C[k][c1] % mod * C[l][c2];
//								tr(i, k, l, m, c1, c2, n1, n2, dp[k][l][m], v);
								if(m-1 > 0){
									ndp[n1][n2][m-1] += v;
									ndp[n1][n2][m-1] %= mod;
								}else if(n1+2*n2+i+1 <= n){
									// 次の層へ
									ndp[0][0][n1+2*n2] += v % mod * ip2[n2];
									ndp[0][0][n1+2*n2] %= mod;
								}
							}
						}
					}
				}
			}
			dp = ndp;
		}
		out.println(dp[0][0][0]);
	}

	public static long invl(long a, long mod) {
		long b = mod;
		long p = 1, q = 0;
		while (b > 0) {
			long c = a / b;
			long d;
			d = a;
			a = b;
			b = d % b;
			d = p;
			p = q;
			q = d - c * q;
		}
		return p < 0 ? p + mod : p;
	}

	void run() throws Exception
	{
//		int n = 50, m = 99999;
//		Random gen = new Random();
//		StringBuilder sb = new StringBuilder();
//		sb.append(n + " ");
//		for (int i = 0; i < n; i++) {
//			sb.append(gen.nextInt(2)+2 + " ");
//		}
//		INPUT = sb.toString();

		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 E2().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.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Div2_418E {

	// solution completely based on that of the editorial

	static final long MOD = 1_000_000_007L;

	static int numV;

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

		numV = Integer.parseInt(reader.readLine());

		int[] deg = new int[numV + 1];
		StringTokenizer inputData = new StringTokenizer(reader.readLine());
		for (int i = 1; i <= numV; i++) {
			deg[i] = Integer.parseInt(inputData.nextToken());
		}
		reader.close();

		// let assign[A][B][C] represent the number of ways to move to a level with A vertices from a level with B
		// 1-opening vertices and C 2-opening vertices
		long[][][] aCnt = new long[numV + 5][numV + 5][numV + 5];

		aCnt[0][0][0] = 1;

		// loop ordering is non-trivial cnt2 has to be before the cnt1 loop
		for (int cntE = 0; cntE <= numV; cntE++) {
			for (int cnt2 = 0; cnt2 <= numV; cnt2++) {
				for (int cnt1 = 0; cnt1 <= numV; cnt1++) {
					long cCnt = 0;

					// ext, ext
					// ext, t1
					// ext, t2
					// t1, t1
					// t1, t2
					// t2, t2

					if (cnt2 > 0) {
						if (cntE > 1) {
							cCnt += aCnt[cntE - 2][cnt1][cnt2 - 1] * cntE * (cntE - 1) >> 1;
						}
						if (cntE > 0 && cnt1 > 0) {
							cCnt += aCnt[cntE - 1][cnt1 - 1][cnt2 - 1] * cntE * cnt1;
						}
						if (cntE > 0 && cnt2 > 1) {
							cCnt += aCnt[cntE - 1][cnt1 + 1][cnt2 - 2] * cntE * (cnt2 - 1);
						}
						if (cnt1 > 1) {
							cCnt += aCnt[cntE][cnt1 - 2][cnt2 - 1] * cnt1 * (cnt1 - 1) >> 1;
						}
						if (cnt1 > 0 && cnt2 > 1) {
							cCnt += aCnt[cntE][cnt1][cnt2 - 2] * cnt1 * (cnt2 - 1);
						}
						if (cnt2 > 2) {
							cCnt += aCnt[cntE][cnt1 + 2][cnt2 - 3] * (cnt2 - 1) * (cnt2 - 2) >> 1;
						}
						cCnt %= MOD;
						aCnt[cntE][cnt1][cnt2] = cCnt;
					} else if (cnt1 > 0) {
						if (cntE > 0) {
							cCnt += aCnt[cntE - 1][cnt1 - 1][0] * cntE;
						}
						if (cnt1 > 1) {
							cCnt += aCnt[cntE][cnt1 - 2][0] * (cnt1 - 1);
						}
						cCnt %= MOD;
						aCnt[cntE][cnt1][cnt2] = cCnt;
					}
				}
			}
		}

		int[] preCnt1 = new int[numV + 1];
		for (int i = 1; i <= numV; i++) {
			preCnt1[i] = deg[i] == 2 ? 1 + preCnt1[i - 1] : preCnt1[i - 1];
		}

		long[][] ans = new long[numV + 5][numV + 5];

		// smart way of initializing everything with the last object to 1
		ans[numV + 1][numV] = 1;

		for (int l = numV; l > 1; l--) {
			for (int r = l; r <= numV; r++) {
				int cnt1 = preCnt1[r] - preCnt1[l - 1];
				int cnt2 = r - l + 1 - cnt1;

				for (int nLevLen = 0; nLevLen <= (cnt2 << 1) + cnt1 && r + nLevLen <= numV; nLevLen++) {
					ans[l][r] = (ans[l][r] + ans[r + 1][r + nLevLen] * aCnt[nLevLen][cnt1][cnt2]) % MOD;
				}
			}
		}

		System.out.println(ans[2][1 + deg[1]]);
	}

}


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

public class CF418E {

    private static final boolean TEST_CASES = false;
    private static final int MOD = 1000000007;
    private final Map<Cache, Integer> dp = new HashMap<>();
    private int n;
    private int[] di;

    void solve(int testCaseNo, InputReader in, PrintWriter out) {
        n = in.nextInt();
        di = new int[n];
        for (int i = 0; i < n; i++) {
            di[i] = in.nextInt();
        }

        out.println(ways(2, 3 - di[0], di[0] - 2, 3 - di[1], di[1] - 2));

    }

    private int ways(int i, int x1, int x2, int y1, int y2) {
        if (x1 < 0 || x2 < 0 || y1 < 0 || y2 < 0) return 0;
        if (i == n) {
            if (x1 != 0 || x2 != 0 || y1 != 0 || y2 != 0)
                return 0;
            return 1;
        }
        int sx = x1 + x2;
        int sy = y1 + y2;
        if ((sx + sy) == 0) return 0;
        if (sx == 0) return ways(i, y1, y2, x1, x2);

        Cache c = new Cache(x1, x2, y1, y2, i);
        if (dp.containsKey(c)) return dp.get(c);

//        System.out.println(i + " " + x1 + " " + x2 + " " + y1 + " " + y2);

        int r = 0;

        if (di[i] == 2) {

            // chose from x1
            // don't assign to same level
            r = add(r, mul(x1, ways(i + 1, x1 - 1, x2, y1 + 1, y2)));

            // assign one to same level one-empty
            r = add(r, mul(x1, y1, ways(i + 1, x1 - 1, x2, y1 - 1, y2)));

            // assign one to same level two-empty
            r = add(r, mul(x1, y2, ways(i + 1, x1 - 1, x2, y1 + 1, y2 - 1)));

            // chose from x2
            // don't assign to same level
            r = add(r, mul(x2, ways(i + 1, x1 + 1, x2 - 1, y1 + 1, y2)));

            // assign one to same level one-empty
            r = add(r, mul(x2, y1, ways(i + 1, x1 + 1, x2 - 1, y1 - 1, y2)));

            // assign one to same level two-empty
            r = add(r, mul(x2, y2, ways(i + 1, x1 + 1, x2 - 1, y1 + 1, y2 - 1)));

        } else {

            // chose from x1
            // don't assign to same level
            r = add(r, mul(x1, ways(i + 1, x1 - 1, x2, y1, y2 + 1)));

            // assign one to same level one-empty
            r = add(r, mul(x1, y1, ways(i + 1, x1 - 1, x2, y1, y2)));

            // assign one to same level two-empty
            r = add(r, mul(x1, y2, ways(i + 1, x1 - 1, x2, y1 + 2, y2 - 1)));

            // assign two to two one-empty
            if (y1 >= 2) r = add(r, mul(x1, ((y1 * (y1 - 1)) / 2), ways(i + 1, x1 - 1, x2, y1 - 2, y2)));
            // assign two: one to one-empty other to two-empty
            r = add(r, mul(mul(x1, y1, y2), ways(i + 1, x1 - 1, x2, y1, y2 - 1)));
            // assign two: both to two-empty
            if (y2 >= 2) r = add(r, mul(x1, ((y2 * (y2 - 1)) / 2), ways(i + 1, x1 - 1, x2, y1 + 2, y2 - 2)));

            // chose from x2
            // don't assign to same level
            r = add(r, mul(x2, ways(i + 1, x1 + 1, x2 - 1, y1, y2 + 1)));

            // assign one to same level one-empty
            r = add(r, mul(x2, y1, ways(i + 1, x1 + 1, x2 - 1, y1, y2)));

            // assign one to same level two-empty
            r = add(r, mul(x2, y2, ways(i + 1, x1 + 1, x2 - 1, y1 + 2, y2 - 1)));

            // assign two to two one-empty
            if (y1 >= 2) r = add(r, mul(x2, ((y1 * (y1 - 1)) / 2), ways(i + 1, x1 + 1, x2 - 1, y1 - 2, y2)));
            // assign two: one to one-empty other to two-empty
            r = add(r, mul(mul(x2, y1, y2), ways(i + 1, x1 + 1, x2 - 1, y1, y2 - 1)));
            // assign two: both to two-empty
            if (y2 >= 2) r = add(r, mul(x2, ((y2 * (y2 - 1)) / 2), ways(i + 1, x1 + 1, x2 - 1, y1 + 2, y2 - 2)));

        }

        dp.put(c, r);
        return r;
    }

    private int add(int a, int b) {
        return (a + b) % MOD;
    }
    private int mul(int a, int b) {
        long t = (long)a * b;
        return (int) (t % MOD);
    }
    private int mul(int a, int b, int c) {
        return mul(a, mul(b, c));
    }

    static class Cache {

        final int x1;
        final int x2;
        final int y1;
        final int y2;
        final int i;

        public Cache(int x1, int x2, int y1, int y2, int i) {
            this.x1 = x1;
            this.x2 = x2;
            this.y1 = y1;
            this.y2 = y2;
            this.i = i;
        }

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

            Cache cache = (Cache) o;

            if (x1 != cache.x1) return false;
            if (x2 != cache.x2) return false;
            if (y1 != cache.y1) return false;
            if (y2 != cache.y2) return false;
            return i == cache.i;
        }

        @Override
        public int hashCode() {
            int result = x1;
            result = 31 * result + x2;
            result = 31 * result + y1;
            result = 31 * result + y2;
            result = 31 * result + i;
            return result;
        }
    }

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

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

        /**
         * @return null if end of stream
         */
        public String readLine() {
            try {
                return reader.readLine();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        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 long nextLong() {
            return Long.parseLong(next());
        }

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

    }

    public static void main(String[] args) {
        InputReader in = new InputReader(System.in);
        PrintWriter out = new PrintWriter(System.out);

        int testCases = TEST_CASES ? in.nextInt() : 1;

        CF418E solver = new CF418E();
        for (int testCase = 0; testCase < testCases; testCase++) {
            solver.solve(testCase, in, out);
        }
        out.flush();
        out.close();
    }
}


//package round418;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

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

	void solve()
	{
		int mod = 1000000007;
		int n = ni();
		int[] ds = na(n);

		long[][] C = new long[50 + 1][50 + 1];
		for (int i = 0; i <= 50; i++) {
			C[i][0] = 1;
			for (int j = 1; j <= i; j++) {
				C[i][j] = C[i - 1][j - 1] + C[i - 1][j];
				if (C[i][j] >= mod)
					C[i][j] -= mod;
			}
		}

		long[] ip2 = new long[50];
		long i2 = invl(2, mod);
		ip2[0] = 1;
		for(int i = 1;i < 50;i++)ip2[i] = ip2[i-1] * i2 % mod;

		// [同層で処理済みの1次の頂点][同層で処理済みの2次の頂点][同層で未処理の頂点]
		long[][][] dp = new long[30][30][30];
		dp[0][0][ds[0]] = ds[0] == 3 ? invl(6, mod) : invl(2, mod);
		for(int i = 1;i < n;i++){
			long[][][] ndp = new long[30][30][30];
			for(int k = 0;k < 30;k++){
				for(int l = 0;k+l < 30;l++){
					for(int m = 1;k+l+m < 30;m++){
						if(dp[k][l][m] == 0)continue;
						// 未処理の点から1個選ぶ
						// 1,2次の頂点と結ぶ
						for(int c1 = 0;c1 <= k && c1 <= ds[i]-1;c1++){
							for(int c2 = 0;c2 <= l && c1+c2 <= ds[i]-1;c2++){
								int n1 = k-c1+c2, n2 = l-c2;
								int pl = ds[i] - 1 - c1 - c2;
								if(pl == 1)n1++;
								if(pl == 2)n2++;
								long v = m * dp[k][l][m] % mod * C[k][c1] % mod * C[l][c2];
//								tr(i, k, l, m, c1, c2, n1, n2, dp[k][l][m], v);
								if(m-1 > 0){
									ndp[n1][n2][m-1] += v;
									ndp[n1][n2][m-1] %= mod;
								}else{
									// 次の層へ
									ndp[0][0][n1+2*n2] += v % mod * ip2[n2];
									ndp[0][0][n1+2*n2] %= mod;
								}
							}
						}
					}
				}
			}
			dp = ndp;
		}
		out.println(dp[0][0][0]);
	}

	public static long invl(long a, long mod) {
		long b = mod;
		long p = 1, q = 0;
		while (b > 0) {
			long c = a / b;
			long d;
			d = a;
			a = b;
			b = d % b;
			d = p;
			p = q;
			q = d - c * q;
		}
		return p < 0 ? p + mod : p;
	}

	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 E2().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 static java.lang.System.out;
import java.util.Scanner;

// 795A
// n people, some pupil, some adult. separate into groups. a group must have 1 adult
// if a group has x people, cost of tickets=c1+c2(x-1)^2
// find minimal price
public class AmusementPark {

    int adult;
    int pupil;
    int n;      // 1 ≤ n ≤ 200 000
    long c1;    // 1 ≤ c1, c2 ≤ 10^7
    long c2;
    long minCost=0;

    long formula(int x)
    {
        return c1+c2*(x-1)*(x-1);
    }
    long calc(int group)
    {
        if (group==1)
        {
            return formula(n);
        }
        int avg = n/group;
        int rem = n%group;
        long cost = formula(avg);
        if ( rem>0 ) {
            cost *= (group-rem);
            return cost + rem*formula(avg+1);
        }
        else
            return cost *group;
    }
    long cost(int lo, int hi, long lowCost, long hiCost)
    {
        if (lo-hi<=1 && lo-hi>=-1) {
            return lowCost;
        }
        int mid = (lo+hi)/2;
        long midCost = calc(mid);
        //out.println("first "+lo+" second "+hi+ " mid cost "+midCost+" low clost "+lowCost+" hi cost "+hiCost);
        if (midCost<lowCost)
            return cost(mid, lo, midCost, lowCost);
        else if ( midCost < hiCost )
            return cost(lo, mid, lowCost, midCost);
        else {
            //out.println("bad mid cost "+midCost+" low clost "+lowCost+" hi cost "+hiCost);
            return midCost;
        }
    }
    AmusementPark(int a, int p, int c1, int c2)
    {
        adult = a;
        pupil = p;
        n = a+p;
        this.c1 = c1;
        this.c2 = c2;
        long cost1 = calc(1);
        long cost2 = calc(a);
        if (cost1>cost2)
            out.println(cost(a, 1, cost2, cost1));
        else if (cost1<cost2)
            out.println(cost(1, a, cost1, cost2));
        else
            out.println(cost1);
    }

    static Scanner scan = new Scanner(System.in);
    static void autoTest()
    {
        int n = scan.nextInt();  // between 1 and 20000
        int c1 = scan.nextInt();  // between 1 and 10^7
        int c2 = scan.nextInt();  // between 1 and 10^7
        String people = scan.nextLine();
        if (people.isEmpty())
            people = scan.nextLine();
        int pupil=0;
        int adult=0;
        for(int i=0; i<people.length(); i++)
        {
            if (people.charAt(i)=='1')
                adult++;
            else
                pupil++;
        }
        new AmusementPark(adult, pupil, c1, c2);
    }
    public static void main(String[] args)
    {
        autoTest();
    }
}
/*
10 2 2
1111101111
ans 20
*/


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.io.InputStreamReader;
import java.io.InputStream;

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

    static class TaskA {
        private int n;
        private int c1;
        private int c2;

        public void solve(int testNumber, MyReader in, PrintWriter out) {
            n = in.nextInt();
            c1 = in.nextInt();
            c2 = in.nextInt();

            String s = in.next();
            int parent = 0;
            for (int i = 0; i < s.length(); i++) {
                if (s.charAt(i) == '1') {
                    parent++;
                }
            }

            // ternary search
            long lo = 1, hi = parent;
            while (hi - lo > 1) {
                long mid = (lo + hi) / 2;
                if (f(mid) > f(mid + 1)) {
                    hi = mid;
                } else {
                    lo = mid;
                }
            }
            if (f(lo) < f(hi)) {
                out.println(f(lo));
            } else {
                out.println(f(hi));
            }

        }

        long f(long v) {
            long p1 = n / v;

            long sum = c1 * v;
            sum += (n % v) * c2 * (p1) * (p1);
            sum += (v - (n % v)) * c2 * (p1 - 1) * (p1 - 1);

            return sum;
        }

    }

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

        public MyReader(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 static java.lang.System.out;
import java.util.Scanner;

// 795A
// n people, some pupil, some adult. separate into groups. a group must have 1 adult
// if a group has x people, cost of tickets=c1+c2(x-1)^2
// find minimal price
public class AmusementPark {

    int adult;
    int pupil;
    int n;
    int c1;
    int c2;
    long minCost=0;

    long formula(int x)
    {
        return c1+c2*(x-1)*(x-1);
    }
    long calc(int group)
    {
        if (group==1)
        {
            return formula(n);
        }
        int avg = n/group;
        int rem = n%group;
        long cost = formula(avg);
        if ( rem>0 ) {
            cost *= (group-rem);
            return cost + rem*formula(avg+1);
        }
        else
            return cost *group;
    }
    long cost(int lo, int hi, long lowCost, long hiCost)
    {
        if (lo-hi<=1 && lo-hi>=-1) {
            return lowCost;
        }
        int mid = (lo+hi)/2;
        long midCost = calc(mid);
        //out.println("first "+lo+" second "+hi+ " mid cost "+midCost+" low clost "+lowCost+" hi cost "+hiCost);
        if (midCost<lowCost)
            return cost(mid, lo, midCost, lowCost);
        else if ( midCost < hiCost )
            return cost(lo, mid, lowCost, midCost);
        else {
            out.println("bad mid cost "+midCost+" low clost "+lowCost+" hi cost "+hiCost);
            return 0;
        }
    }
    AmusementPark(int a, int p, int c1, int c2)
    {
        adult = a;
        pupil = p;
        n = a+p;
        this.c1 = c1;
        this.c2 = c2;
        long cost1 = calc(1);
        long cost2 = calc(a);
        if (cost1>cost2)
            out.println(cost(a, 1, cost2, cost1));
        else if (cost1<cost2)
            out.println(cost(1, a, cost1, cost2));
        else
            out.println(cost1);
    }

    static Scanner scan = new Scanner(System.in);
    static void autoTest()
    {
        int n = scan.nextInt();  // between 1 and 20000
        int c1 = scan.nextInt();  // between 1 and 10^7
        int c2 = scan.nextInt();  // between 1 and 10^7
        String people = scan.nextLine();
        if (people.isEmpty())
            people = scan.nextLine();
        int pupil=0;
        int adult=0;
        for(int i=0; i<people.length(); i++)
        {
            if (people.charAt(i)=='1')
                adult++;
            else
                pupil++;
        }
        new AmusementPark(adult, pupil, c1, c2);
    }
    public static void main(String[] args)
    {
        autoTest();
    }
}


import static java.lang.System.out;
import java.util.Scanner;

// 795A
// n people, some pupil, some adult. separate into groups. a group must have 1 adult
// if a group has x people, cost of tickets=c1+c2(x-1)^2
// find minimal price
public class AmusementPark {

    int adult;
    int pupil;
    int n;
    int c1;
    int c2;
    long minCost=0;

    long formula(int x)
    {
        return c1+c2*(x-1)*(x-1);
    }
    long calc(int group)
    {
        if (group==1)
        {
            return formula(n);
        }
        int avg = n/group;
        int rem = n%group;
        long cost = formula(avg);
        if ( rem>0 ) {
            cost *= (group-rem);
            return cost + rem*formula(avg+1);
        }
        else
            return cost *group;
    }
    long cost(int lo, int hi, long lowCost, long hiCost)
    {
        if (lo-hi<=1 && lo-hi>=-1) {
            return lowCost;
        }
        int mid = (lo+hi)/2;
        long midCost = calc(mid);
        //out.println("first "+lo+" second "+hi+ " mid cost "+midCost+" low clost "+lowCost+" hi cost "+hiCost);
        if (midCost<lowCost)
            return cost(mid, lo, midCost, lowCost);
        else if ( midCost < hiCost )
            return cost(lo, mid, lowCost, midCost);
        else {
            //out.println("bad mid cost "+midCost+" low clost "+lowCost+" hi cost "+hiCost);
            return midCost;
        }
    }
    AmusementPark(int a, int p, int c1, int c2)
    {
        adult = a;
        pupil = p;
        n = a+p;
        this.c1 = c1;
        this.c2 = c2;
        long cost1 = calc(1);
        long cost2 = calc(a);
        if (cost1>cost2)
            out.println(cost(a, 1, cost2, cost1));
        else if (cost1<cost2)
            out.println(cost(1, a, cost1, cost2));
        else
            out.println(cost1);
    }

    static Scanner scan = new Scanner(System.in);
    static void autoTest()
    {
        int n = scan.nextInt();  // between 1 and 20000
        int c1 = scan.nextInt();  // between 1 and 10^7
        int c2 = scan.nextInt();  // between 1 and 10^7
        String people = scan.nextLine();
        if (people.isEmpty())
            people = scan.nextLine();
        int pupil=0;
        int adult=0;
        for(int i=0; i<people.length(); i++)
        {
            if (people.charAt(i)=='1')
                adult++;
            else
                pupil++;
        }
        new AmusementPark(adult, pupil, c1, c2);
    }
    public static void main(String[] args)
    {
        autoTest();
    }
}
/*
10 2 2
1111101111
ans 20
*/


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.BufferedWriter;
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);
        TaskD solver = new TaskD();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskD {
        public void solve(int testNumber, InputReader in, OutputWriter out) {
            out.print(1);
        }

    }

    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 print(int i) {
            writer.print(i);
        }

    }

    static class InputReader {
        private InputStream stream;

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

    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.util.TreeSet;

public class D {

	public static void main(String[] args) throws Exception {
		FastScanner scan = new FastScanner();
		PrintWriter out = new PrintWriter(System.out);
		char[] in = scan.next().toCharArray();
		int res = 0;
		for(int i = 0; i < in.length; i++) if(in[i] == '1') res++;
		out.println(res);
		out.close();
	}

	static class FastScanner {
		BufferedReader br;
		StringTokenizer st;

		public FastScanner() {
			try	{
				br = new BufferedReader(new InputStreamReader(System.in));
				st = new StringTokenizer(br.readLine());
			} catch (Exception e){e.printStackTrace();}
		}

		public String next() {
			if (st.hasMoreTokens())	return st.nextToken();
			try {st = new StringTokenizer(br.readLine());}
			catch (Exception e) {e.printStackTrace();}
			return st.nextToken();
		}

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

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

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

		public String nextLine() {
			String line = "";
			if(st.hasMoreTokens()) line = st.nextToken();
			else try {return br.readLine();}catch(IOException e){e.printStackTrace();}
			while(st.hasMoreTokens()) line += " "+st.nextToken();
			return line;
		}

		public int[] nextIntArray(int n) {
			int[] a = new int[n];
			for(int i = 0; i < n; i++) a[i] = nextInt();
			return a;
		}

		public long[] nextLongArray(int n){
			long[] a = new long[n];
			for(int i = 0; i < n; i++) a[i] = nextLong();
			return a;
		}

		public double[] nextDoubleArray(int n){
			double[] a = new double[n];
			for(int i = 0; i < n; i++) a[i] = nextDouble();
			return a;
		}

		public char[][] nextGrid(int n, int m){
			char[][] grid = new char[n][m];
			for(int i = 0; i < n; i++) grid[i] = next().toCharArray();
			return grid;
		}
	}

}


import java.util.*;
public class D
{
public static void main(String[] args)
{
    Scanner sc = new Scanner(System.in);
    System.out.println(Integer.toString(sc.next(),8).replaceAll("[^1]","").length());
}
}


import java.util.Scanner;

public class SPENCERISGOD {

	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		int n = scan.nextInt();
		boolean spencerIsGod = true;
		while (spencerIsGod) { //AKA always
			System.out.println("ALL PRAISE TO SPENCER, OUR LORD AND SAVIOR, CREATOR OF THE SACRED THREE LOOP. HE HAS DELIVERED US FROM OUR PROCEDURAL PROGRAMMING, AND SHOWED US THE LIGHT OF OBJECT-ORIENTED. MAY HIS CODE FOREVER BE AS PERFECT AS HE IS, FOREVER AND EVER, A-JAVA.");
		}
	}
}


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;
        }
    }
}


//package round97;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;

public class E2 {
	InputStream is;
	PrintWriter out;
	String INPUT = "1000000 1000000000";
//	String INPUT = "2 139";
//	String INPUT = "2 139";
	int mod = 1000000007;

	long[] PS = new long[1000002];
	long[] IPS = new long[1000002];
	long[] KE = new long[1000002];
	long[] KE2 = new long[1000020];

	void solve()
	{
		int k = ni(), w = ni();
		long sum = 0;
		PS[0] = 1;
		IPS[0] = 1;
		KE[0] = modpow(k, w, mod);
		KE2[0] = modpow(k, w+4, mod);
		long ik = inv(k, mod);
		for(int i = 1;i <= k+1;i++){
			PS[i] = PS[i-1]*(k-i+1)%mod;
			IPS[i] = IPS[i-1]*inv(k-i+1, mod)%mod;
			KE[i] = KE[i-1] * k % mod;
		}
		for(int i = 1;i <= k+19;i++){
			KE2[i] = KE2[i-1] * ik % mod;
		}
		gw = w;
		for(int l = w+1;l <= w+k;l++){
			long v = (val(k, w, l) - val(k, w+1, l)) % mod;
			sum += v;
//			tr(l, v);
		}
		out.println((sum%mod+mod)%mod);
	}

	public static long inv(long a, int p)
	{
		long ret = 1;
		long mul = a;
		for(long n = p-2;n > 0;n >>>= 1){
			if((n&1)==1)ret = ret * mul % p;
			mul = mul * mul % p;
		}
		return ret;
	}

	int gw;

	// k=2,W=2,L=3
	// 8

	int gct = 0;
	//
	// OXO
	long val(long k, long W, long L)
	{
		if(W >= L)return 0;
		// headで含む
		// tailで含む
		// 2W-L+2=W+2-(L-W)
		long ret;
		if(W > L+1-W){
//			ret = modpow(k, L, mod) - modpow(k, L-2*(L-W+1), mod) * modpow(P(k, L-W+1), 2, mod)%mod;
			ret = KE[(int)(L-gw)] - KE2[(int)(gw+4-(L-2*(L-W+1)))] * modpow(P(k, L-W+1), 2, mod)%mod;
		}else{
			long p = k-(L-2*(W-1)) < W-1 ? 0 : P(k, (L-2*(W-1))+(W-1))*invP(k, L-2*(W-1))%mod;
//			ret = modpow(k, L, mod) - P(k,L-2*(W-1))*modpow(p, 2, mod)%mod;
			ret = KE[(int)(L-gw)] - P(k,L-2*(W-1))*modpow(p, 2, mod)%mod;
		}

		return (int)((ret%mod+mod)%mod);
	}

	long P(long n, long r)
	{
		if(r > n)return 0;
		return PS[(int)r];
	}

	long invP(long n, long r)
	{
		if(r > n)return 0;
		return IPS[(int)r];
	}

	public static long modpow(long a, long n, long mod)
	{
		long ret = 1;
		long mul = a;
		for(;n > 0;n >>>= 1){
			if((n&1)==1){
				ret = (ret * mul) % mod;
			}
			mul = (mul * mul) % mod;
		}
		return ret;
	}

	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 E2().run();
	}

	public int ni()
	{
		try {
			int num = 0;
			boolean minus = false;
			while((num = is.read()) != -1 && !((num >= '0' && num <= '9') || num == '-'));
			if(num == '-'){
				num = 0;
				minus = true;
			}else{
				num -= '0';
			}

			while(true){
				int b = is.read();
				if(b >= '0' && b <= '9'){
					num = num * 10 + (b - '0');
				}else{
					return minus ? -num : num;
				}
			}
		} catch (IOException e) {
		}
		return -1;
	}

	public long nl()
	{
		try {
			long num = 0;
			boolean minus = false;
			while((num = is.read()) != -1 && !((num >= '0' && num <= '9') || num == '-'));
			if(num == '-'){
				num = 0;
				minus = true;
			}else{
				num -= '0';
			}

			while(true){
				int b = is.read();
				if(b >= '0' && b <= '9'){
					num = num * 10 + (b - '0');
				}else{
					return minus ? -num : num;
				}
			}
		} catch (IOException e) {
		}
		return -1;
	}

	public String ns()
	{
		try{
			int b = 0;
			StringBuilder sb = new StringBuilder();
			while((b = is.read()) != -1 && (b == '\r' || b == '\n' || b == ' '));
			if(b == -1)return "";
			sb.append((char)b);
			while(true){
				b = is.read();
				if(b == -1)return sb.toString();
				if(b == '\r' || b == '\n' || b == ' ')return sb.toString();
				sb.append((char)b);
			}
		} catch (IOException e) {
		}
		return "";
	}

	public char[] ns(int n)
	{
		char[] buf = new char[n];
		try{
			int b = 0, p = 0;
			while((b = is.read()) != -1 && (b == ' ' || b == '\r' || b == '\n'));
			if(b == -1)return null;
			buf[p++] = (char)b;
			while(p < n){
				b = is.read();
				if(b == -1 || b == ' ' || b == '\r' || b == '\n')break;
				buf[p++] = (char)b;
			}
			return Arrays.copyOf(buf, p);
		} catch (IOException e) {
		}
		return null;
	}

	double nd() { return Double.parseDouble(ns()); }
	boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}


//package round97;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;

public class E2 {
	InputStream is;
	PrintWriter out;
	String INPUT = "";
//	String INPUT = "2 139";
//	String INPUT = "2 139";
	int mod = 1000000007;

	long[] PS = new long[1000001];
	long[] IPS = new long[1000001];
	long[] KE = new long[1000002];
	long[] KE2 = new long[1000020];

	void solve()
	{
		int k = ni(), w = ni();
		long sum = 0;
		PS[0] = 1;
		IPS[0] = 1;
		KE[0] = modpow(k, w, mod);
		KE2[0] = modpow(k, w+4, mod);
		long ik = inv(k, mod);
		for(int i = 1;i <= k;i++){
			PS[i] = PS[i-1]*(k-i+1)%mod;
			IPS[i] = IPS[i-1]*inv(k-i+1, mod)%mod;
			KE[i] = KE[i-1] * k % mod;
		}
		for(int i = 1;i <= k+19;i++){
			KE2[i] = KE2[i-1] * ik % mod;
		}
		gw = w;
		for(int l = w+1;l <= w+k;l++){
			long v = (val(k, w, l) - val(k, w+1, l)) % mod;
			sum += v;
//			tr(l, v);
		}
		out.println((sum%mod+mod)%mod);
	}

	public static long inv(long a, int p)
	{
		long ret = 1;
		long mul = a;
		for(long n = p-2;n > 0;n >>>= 1){
			if((n&1)==1)ret = ret * mul % p;
			mul = mul * mul % p;
		}
		return ret;
	}

	int gw;

	// k=2,W=2,L=3
	// 8

	int gct = 0;
	//
	// OXO
	long val(long k, long W, long L)
	{
		if(W >= L)return 0;
		// headで含む
		// tailで含む
		// 2W-L+2=W+2-(L-W)
		long ret;
		if(W > L+1-W){
//			ret = modpow(k, L, mod) - modpow(k, L-2*(L-W+1), mod) * modpow(P(k, L-W+1), 2, mod)%mod;
			ret = KE[(int)(L-gw)] - KE2[(int)(gw+4-(L-2*(L-W+1)))] * modpow(P(k, L-W+1), 2, mod)%mod;
		}else{
//			long p = k-(L-2*(W-1)) < W-1 ? 0 : P(k, W-1)*inv(P(k, L-2*(W-1)), mod)%mod;
			long p = k-(L-2*(W-1)) < W-1 ? 0 : P(k, W-1)*invP(k, L-2*(W-1))%mod;
//			ret = modpow(k, L, mod) - P(k,L-2*(W-1))*modpow(p, 2, mod)%mod;
			ret = KE[(int)(L-gw)] - P(k,L-2*(W-1))*modpow(p, 2, mod)%mod;
		}

		return (int)((ret%mod+mod)%mod);
	}

	long P(long n, long r)
	{
		if(r > n)return 0;
		return PS[(int)r];
	}

	long invP(long n, long r)
	{
		if(r > n)return 0;
		return IPS[(int)r];
	}

	public static long modpow(long a, long n, long mod)
	{
		long ret = 1;
		long mul = a;
		for(;n > 0;n >>>= 1){
			if((n&1)==1){
				ret = (ret * mul) % mod;
			}
			mul = (mul * mul) % mod;
		}
		return ret;
	}

	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 E2().run();
	}

	public int ni()
	{
		try {
			int num = 0;
			boolean minus = false;
			while((num = is.read()) != -1 && !((num >= '0' && num <= '9') || num == '-'));
			if(num == '-'){
				num = 0;
				minus = true;
			}else{
				num -= '0';
			}

			while(true){
				int b = is.read();
				if(b >= '0' && b <= '9'){
					num = num * 10 + (b - '0');
				}else{
					return minus ? -num : num;
				}
			}
		} catch (IOException e) {
		}
		return -1;
	}

	public long nl()
	{
		try {
			long num = 0;
			boolean minus = false;
			while((num = is.read()) != -1 && !((num >= '0' && num <= '9') || num == '-'));
			if(num == '-'){
				num = 0;
				minus = true;
			}else{
				num -= '0';
			}

			while(true){
				int b = is.read();
				if(b >= '0' && b <= '9'){
					num = num * 10 + (b - '0');
				}else{
					return minus ? -num : num;
				}
			}
		} catch (IOException e) {
		}
		return -1;
	}

	public String ns()
	{
		try{
			int b = 0;
			StringBuilder sb = new StringBuilder();
			while((b = is.read()) != -1 && (b == '\r' || b == '\n' || b == ' '));
			if(b == -1)return "";
			sb.append((char)b);
			while(true){
				b = is.read();
				if(b == -1)return sb.toString();
				if(b == '\r' || b == '\n' || b == ' ')return sb.toString();
				sb.append((char)b);
			}
		} catch (IOException e) {
		}
		return "";
	}

	public char[] ns(int n)
	{
		char[] buf = new char[n];
		try{
			int b = 0, p = 0;
			while((b = is.read()) != -1 && (b == ' ' || b == '\r' || b == '\n'));
			if(b == -1)return null;
			buf[p++] = (char)b;
			while(p < n){
				b = is.read();
				if(b == -1 || b == ' ' || b == '\r' || b == '\n')break;
				buf[p++] = (char)b;
			}
			return Arrays.copyOf(buf, p);
		} catch (IOException e) {
		}
		return null;
	}

	double nd() { return Double.parseDouble(ns()); }
	boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}


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

public class Main {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		PrintWriter out = new PrintWriter(System.out);

		Task solver = new Task();
		solver.solve(in, out);
		out.close();
	}
}

class Task {
	final static int MAXN = 211111;
	final static long MD = 1000000007;
	long[] inv, fact, factInv;

	long pow(int x, int y) {
		long ret = 1, tmp = x;
		for (; y > 0; y >>= 1) {
			if ((y & 1) == 1)
				ret = ret * tmp % MD;
			tmp = tmp * tmp % MD;
		}
		return ret;
	}

	long perm(int n, int m) {
		return n < m ? 0 : fact[n] * factInv[n - m] % MD;
	}

	void solve(Scanner in, PrintWriter out) {
		int k = in.nextInt(), w = in.nextInt();
		inv = new long[MAXN];
		fact = new long[MAXN];
		factInv = new long[MAXN];
		inv[1] = 1;
		for (int i = 2; i < MAXN; ++i)
			inv[i] = (MD - MD / i * inv[(int)MD % i] % MD) % MD;

		fact[0] = factInv[0] = 1;
		for (int i = 1; i < MAXN; ++i) {
			fact[i] = fact[i - 1] * i % MD;
			factInv[i] = factInv[i - 1] * inv[i] % MD;
		}

		long ans = 0;
		for (int t = 1; t <= k; ++t) {
			if (w - 1 >= t)
				ans = (ans + perm(k, t) * perm(k, t) % MD * t % MD * pow(k, w - 1 - t) % MD) % MD;
			else
				ans = (ans + perm(k, t) * perm(k - t + w - 1, w - 1) % MD * w % MD) % MD;
			if (w - 1 >= t + 1)
				ans = (ans + perm(k, t) * perm(k, t + 1) % MD * t % MD * pow(k, w - 2 - t) % MD) % MD;
			else
				ans = (ans + perm(k, t) * perm(k - 2 - t + w, w - 1) % MD * (w - 1) % MD) % MD;
		}

		out.println(ans);
	}
}


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

public class Main
{
	static int MOD = 1000000007;
	static long dfac[],fac[];

	public static int A(int n,int r)
	{
		return (int)((long)fac[n] * dfac[n-r] % MOD);
	}

	public static int quickPow(int x,int n)
	{
		long ans = 1;
		for (;n != 0;n >>= 1)
		{
			if ((n & 1) != 0) ans = ans * x % MOD;
			x = (int)((long) x * (long) x % MOD);
		}
		return (int)ans;
	}

	public static int eat(int len,int k,int w)
	{
		long ret = A(k,len);
		int delta = len - (w - 1);
		if (delta >= 0)
		{
			ret = ret * A(k-delta,len-delta) % MOD;
		}
		else
		{
			ret = ret * A(k,len) % MOD;
			ret = ret * quickPow(k,w-1-len) % MOD;
		}
		return (int)ret;
	}

	public static int fuck(int k,int w,boolean inclusive)
	{
		long ret = 0;
		for (int i = inclusive ? 1 : 2;i <= k;++i)
			ret = (ret + eat(i,k,w)) % MOD;
		return (int)ret;
	}

	public static int gao(int k,int w)
	{
		fac = new long[k+1];
		dfac = new long[k+1];
		fac[0] = dfac[0] = 1;
		for (int i = 1;i <= k;++i)
		{
			fac[i] = fac[i-1] * i % MOD;
			dfac[i] = quickPow((int)fac[i],MOD-2);
		}
		return ( (fuck(k,w+1,true) - fuck(k,w,false) ) % MOD + MOD) % MOD;
	}

	public static void main(String args[])
	{
		Scanner cin = new Scanner(System.in);
		int k = cin.nextInt(), w = cin.nextInt();
		System.out.println(gao(k,w));
	}
}


//package bubblecup13.f;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

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

	void solve()
	{
		int n = ni(), Q = ni(), K = ni();
		int[][] qs = new int[Q][];
		int[] day = new int[Q+1];
		int d = 1;
		for(int z = 0;z < Q;z++){
			int t = ni();
			if(t == 1){
				qs[z] = new int[]{t, ni()-1, ni()-1};
			}else if(t == 2){
				qs[z] = new int[]{t, ni()-1};
			}else{
				qs[z] = new int[]{t};
			}
		}
		for(int i = 0;i < Q;i++){
			if(qs[i][0] == 3){
				day[d++] = i;
			}
		}

		QuerySegmentTree qst = new QuerySegmentTree(Q);
		int da = 0;
		for(int i = 0;i < Q;i++){
			if(qs[i][0] == 1){
				if(da+K >= d){
					qst.put(i, Q, i);
				}else{
					qst.put(i, day[da+K], i);
				}
			}else if(qs[i][0] == 3){
				da++;
			}
		}

		RestorableDisjointSet2 rds = new RestorableDisjointSet2(n, Q);

		// process
		int[] stack = new int[30];
		int sp = 0;

		for(int i = 0;i < qs.length;i++){
			int upd = Integer.bitCount((i^i-1)&(qst.M-1));
			if(i > 0){
				for(int j = 0;j < upd;j++){
					// pop
					rds.revert(stack[--sp]);
				}
			}
			for(int j = upd-1;j >= 0;j--){
				// push
				L node = qst.st[qst.H+i>>>j];
				stack[sp++] = rds.hp;
				if(node != null){
					for(int k = 0;k < node.size();k++){
						int id = node.a[k];
						rds.union(qs[id][1], qs[id][2]);
					}
				}
			}

			if(qs[i][0] == 2){
				int[] q = qs[i];
				out.println(-rds.upper[rds.root(q[1])]);
			}
		}
	}

	public static class L {
		public int[] a;
		public int p = 0;

		public L(int n) { a = new int[n]; }
		public L add(int n)
		{
			if(p >= a.length)a = Arrays.copyOf(a, a.length*3/2+1);
			a[p++] = n;
			return this;
		}
		public int size() { return p; }
		public L clear() { p = 0; return this; }
		public int[] toArray() { return Arrays.copyOf(a, p); }
		@Override
		public String toString() {return Arrays.toString(toArray());}
	}

	public static class RestorableDisjointSet2 {
		public int[] upper; // minus:num_element(root) plus:root(normal)
		private int[] targets;
		private int[] histupper;
		public int hp = 0;

		public RestorableDisjointSet2(int n, int m)
		{
			upper = new int[n];
			Arrays.fill(upper, -1);

			targets = new int[2*m];
			histupper = new int[2*m];
			//
			//			w = new int[n];
		}

		public RestorableDisjointSet2(RestorableDisjointSet2 ds)
		{
			this.upper = Arrays.copyOf(ds.upper, ds.upper.length);
			this.histupper = Arrays.copyOf(ds.histupper, ds.histupper.length);
			//
			this.hp = ds.hp;
		}

		public int root(int x)
		{
			return upper[x] < 0 ? x : root(upper[x]);
		}

		public boolean equiv(int x, int y)
		{
			return root(x) == root(y);
		}

		public boolean union(int x, int y)
		{
			x = root(x);
			y = root(y);
			if(x != y) {
				if(upper[y] < upper[x]) {
					int d = x; x = y; y = d;
				}
				//				w[x] += w[y];
				record(x); record(y);
				upper[x] += upper[y];
				//
				upper[y] = x;
			}
			return x == y;
		}

		public int time() { return hp; }

		private void record(int x)
		{
			targets[hp] = x;
			histupper[hp] = upper[x];
			//
			hp++;
		}

		public void revert(int to)
		{
			while(hp > to){
				upper[targets[hp-1]] = histupper[hp-1];
				//
				hp--;
			}
		}

		public int count()
		{
			int ct = 0;
			for(int u : upper){
				if(u < 0)ct++;
			}
			return ct;
		}

		public int[][] makeUp()
		{
			int n = upper.length;
			int[][] ret = new int[n][];
			int[] rp = new int[n];
			for(int i = 0;i < n;i++){
				if(upper[i] < 0)ret[i] = new int[-upper[i]];
			}
			for(int i = 0;i < n;i++){
				int r = root(i);
				ret[r][rp[r]++] = i;
			}
			return ret;
		}

	}

	public static class QuerySegmentTree
	{
		public int M, H, N;
		public L[] st;

		public QuerySegmentTree(int n)
		{
			N = n;
			M = Integer.highestOneBit(Math.max(N-1, 1))<<2;
			H = M>>>1;
			st = new L[M];
		}

		public void put(int l, int r, int qid){
			if(l >= r)return;
			while(l != 0){
				int f = l&-l;
				if(l+f > r)break;
				L q = st[(H+l)/f];
				if(q == null)q = st[(H+l)/f] = new L(1);
				q.add(qid);
				l += f;
			}

			while(l < r){
				int f = r&-r;
				L q = st[(H+r)/f-1];
				if(q == null)q = st[(H+r)/f-1] = new L(1);
				q.add(qid);
				r -= f;
			}
		}

	}

	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 H().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.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Collection;
import java.io.IOException;
import java.util.ArrayDeque;
import java.util.Deque;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) throws Exception {
        Thread thread = new Thread(null, new TaskAdapter(), "", 1 << 29);
        thread.start();
        thread.join();
    }

    static class TaskAdapter implements Runnable {
        @Override
        public void run() {
            InputStream inputStream = System.in;
            OutputStream outputStream = System.out;
            FastInput in = new FastInput(inputStream);
            PrintWriter out = new PrintWriter(outputStream);
            HVirus solver = new HVirus();
            solver.solve(1, in, out);
            out.close();
        }
    }

    static class HVirus {
        public void solve(int testNumber, FastInput in, PrintWriter out) {
            int n = in.readInt();
            int q = in.readInt();
            int k = in.readInt();
            IntegerDeque dq = new IntegerDequeImpl(q);
            DSU dsu = new DSU(n);
            OperationQueue queue = new OperationQueue(q);
            int day = 0;
            for (int i = 0; i < q; i++) {
                int t = in.readInt();
                if (t == 1) {
                    int x = in.readInt() - 1;
                    int y = in.readInt() - 1;
                    dq.addLast(day);
                    dsu.merge(x, y, queue);
                } else if (t == 2) {
                    int x = in.readInt() - 1;
                    out.println(dsu.size(x));
                } else {
                    day++;
                    while (!dq.isEmpty() && day - dq.peekFirst() >= k) {
                        dq.removeFirst();
                        queue.remove();
                    }
                }
            }
        }

    }

    static class DSU {
        int[] rank;
        int[] p;

        public DSU(int n) {
            rank = new int[n];
            p = new int[n];
            Arrays.fill(rank, 1);
            Arrays.fill(p, -1);
        }

        public int find(int x) {
            while (p[x] != -1) {
                x = p[x];
            }
            return x;
        }

        public int size(int x) {
            return rank[find(x)];
        }

        public void merge(int a, int b, OperationQueue queue) {
            queue.add(new OperationQueue.CommutativeOperation() {
                int x, y;

                public void apply() {
                    x = find(a);
                    y = find(b);
                    if (x == y) {
                        return;
                    }
                    if (rank[x] < rank[y]) {
                        int tmp = x;
                        x = y;
                        y = tmp;
                    }
                    p[y] = x;
                    rank[x] += rank[y];
                }

                public void undo() {
                    int cur = y;
                    while (p[cur] != -1) {
                        cur = p[cur];
                        rank[cur] -= rank[y];
                    }
                    p[y] = -1;
                }
            });
        }

    }

    static interface Operation {
        void apply();

        void undo();

    }

    static interface IntegerIterator {
        boolean hasNext();

        int next();

    }

    static class OperationQueue {
        private Deque<OperationQueue.CommutativeOperation> dq;
        private Deque<OperationQueue.CommutativeOperation> bufA;
        private Deque<OperationQueue.CommutativeOperation> bufB;

        public OperationQueue(int size) {
            dq = new ArrayDeque<>(size);
            bufA = new ArrayDeque<>(size);
            bufB = new ArrayDeque<>(size);
        }

        public void add(OperationQueue.CommutativeOperation op) {
            pushAndDo(op);
        }

        private void pushAndDo(OperationQueue.CommutativeOperation op) {
            dq.addLast(op);
            op.apply();
        }

        private void popAndUndo() {
            OperationQueue.CommutativeOperation ans = dq.removeLast();
            ans.undo();
            if (ans.a) {
                bufA.addLast(ans);
            } else {
                bufB.addLast(ans);
            }
        }

        public void remove() {
            if (!dq.peekLast().a) {
                popAndUndo();
                while (!dq.isEmpty() && bufB.size() != bufA.size()) {
                    popAndUndo();
                }
                if (dq.isEmpty()) {
                    while (!bufB.isEmpty()) {
                        OperationQueue.CommutativeOperation ans = bufB.removeFirst();
                        ans.a = true;
                        pushAndDo(ans);
                    }
                } else {
                    while (!bufB.isEmpty()) {
                        OperationQueue.CommutativeOperation ans = bufB.removeLast();
                        pushAndDo(ans);
                    }
                }
                while (!bufA.isEmpty()) {
                    pushAndDo(bufA.removeLast());
                }
            }

            dq.removeLast().undo();
        }

        public static abstract class CommutativeOperation implements Operation {
            private boolean a;

        }

    }

    static interface IntegerStack {
        void addLast(int x);

        boolean isEmpty();

    }

    static class IntegerDequeImpl implements IntegerDeque {
        private int[] data;
        private int bpos;
        private int epos;
        private static final int[] EMPTY = new int[0];
        private int n;

        public IntegerDequeImpl(int cap) {
            if (cap == 0) {
                data = EMPTY;
            } else {
                data = new int[cap];
            }
            bpos = 0;
            epos = 0;
            n = cap;
        }

        private void expandSpace(int len) {
            while (n < len) {
                n = Math.max(n + 10, n * 2);
            }
            int[] newData = new int[n];
            if (bpos <= epos) {
                if (bpos < epos) {
                    System.arraycopy(data, bpos, newData, 0, epos - bpos);
                }
            } else {
                System.arraycopy(data, bpos, newData, 0, data.length - bpos);
                System.arraycopy(data, 0, newData, data.length - bpos, epos);
            }
            epos = size();
            bpos = 0;
            data = newData;
        }

        public IntegerIterator iterator() {
            return new IntegerIterator() {
                int index = bpos;

                public boolean hasNext() {
                    return index != epos;
                }

                public int next() {
                    int ans = data[index];
                    index = IntegerDequeImpl.this.next(index);
                    return ans;
                }
            };
        }

        public int removeFirst() {
            int ans = data[bpos];
            bpos = next(bpos);
            return ans;
        }

        public void addLast(int x) {
            ensureMore();
            data[epos] = x;
            epos = next(epos);
        }

        public int peekFirst() {
            return data[bpos];
        }

        private int next(int x) {
            return x + 1 >= n ? 0 : x + 1;
        }

        private void ensureMore() {
            if (next(epos) == bpos) {
                expandSpace(n + 1);
            }
        }

        public int size() {
            int ans = epos - bpos;
            if (ans < 0) {
                ans += data.length;
            }
            return ans;
        }

        public boolean isEmpty() {
            return bpos == epos;
        }

        public String toString() {
            StringBuilder builder = new StringBuilder();
            for (IntegerIterator iterator = iterator(); iterator.hasNext(); ) {
                builder.append(iterator.next()).append(' ');
            }
            return builder.toString();
        }

    }

    static interface IntegerDeque extends IntegerStack {
        int removeFirst();

        int peekFirst();

    }

    static class FastInput {
        private final InputStream is;
        private byte[] buf = new byte[1 << 13];
        private int bufLen;
        private int bufOffset;
        private int next;

        public FastInput(InputStream is) {
            this.is = is;
        }

        private int read() {
            while (bufLen == bufOffset) {
                bufOffset = 0;
                try {
                    bufLen = is.read(buf);
                } catch (IOException e) {
                    bufLen = -1;
                }
                if (bufLen == -1) {
                    return -1;
                }
            }
            return buf[bufOffset++];
        }

        public void skipBlank() {
            while (next >= 0 && next <= 32) {
                next = read();
            }
        }

        public int readInt() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            int val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

    }
}


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

public class MainD {
	static final StdIn in = new StdIn();
	static final PrintWriter out = new PrintWriter(System.out);
	static final int mxC=(int)1e5;
	static final long INF=(long)1e10;
	static int n=in.nextInt(), a=in.nextInt()-1, b=in.nextInt()-1;
	static int[] g = in.readIntArray(n-1), k = in.readIntArray(n), nd = new int[n];

	public static void main(String[] args) {
		boolean[] vis = new boolean[mxC+1];
		vis[k[a]]=true;
		for(int i1=a+1, i2=a; i1<n; ++i1) {
			while(i2>0&&!vis[g[i1-1]])
				vis[k[--i2]]=true;
			if(i2==0&&!vis[g[i1-1]])
				i2=-1;
			nd[i1]=i2;
			vis[k[i1]]=true;
		}
		Arrays.fill(vis, false);
		vis[k[a]]=true;
		for(int i1=a-1, i2=a; i1>=0; --i1) {
			while(i2<n-1&&!vis[g[i1]])
				vis[k[++i2]]=true;
			if(i2==n-1&&!vis[g[i1]])
				i2=n;
			nd[i1]=i2;
			vis[k[i1]]=true;
		}
		long ans=cans(b, -1, n);
		out.println(ans>=INF?-1:ans);
		out.close();
	}

	static long cans(int d, int lb, int rb) {
		if(nd[d]<=lb||nd[d]>=rb)
			return INF;
		if(nd[d]==a)
			return Math.abs(d-a);
		return Math.abs(d-nd[d])+(nd[d]!=a?(d<a?cans(nd[d], d, rb):cans(nd[d], lb, d)):0);
	}

	static class StdIn {
		final private int BUFFER_SIZE = 1 << 16;
		private DataInputStream din;
		private byte[] buffer;
		private int bufferPointer, bytesRead;
		public StdIn() {
			din = new DataInputStream(System.in);
			buffer = new byte[BUFFER_SIZE];
			bufferPointer = bytesRead = 0;
		}
		public StdIn(InputStream in) {
			try{
				din = new DataInputStream(in);
			} catch(Exception e) {
				throw new RuntimeException();
			}
			buffer = new byte[BUFFER_SIZE];
			bufferPointer = bytesRead = 0;
		}
		public String next() {
			int c;
			while((c=read())!=-1&&(c==' '||c=='\n'||c=='\r'));
			StringBuilder s = new StringBuilder();
			while (c != -1)
			{
				if (c == ' ' || c == '\n'||c=='\r')
					break;
				s.append((char)c);
				c=read();
			}
			return s.toString();
		}
		public String nextLine() {
			int c;
			while((c=read())!=-1&&(c==' '||c=='\n'||c=='\r'));
			StringBuilder s = new StringBuilder();
			while (c != -1)
			{
				if (c == '\n'||c=='\r')
					break;
				s.append((char)c);
				c = read();
			}
			return s.toString();
		}
		public int nextInt() {
			int ret = 0;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();
			do
				ret = ret * 10 + c - '0';
			while ((c = read()) >= '0' && c <= '9');

			if (neg)
				return -ret;
			return ret;
		}
		public int[] readIntArray(int n) {
			int[] ar = new int[n];
			for(int i=0; i<n; ++i)
				ar[i]=nextInt();
			return ar;
		}
		public long nextLong() {
			long ret = 0;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();
			do
				ret = ret * 10 + c - '0';
			while ((c = read()) >= '0' && c <= '9');
			if (neg)
				return -ret;
			return ret;
		}
		public long[] readLongArray(int n) {
			long[] ar = new long[n];
			for(int i=0; i<n; ++i)
				ar[i]=nextLong();
			return ar;
		}
		public double nextDouble() {
			double ret = 0, div = 1;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();
			do
				ret = ret * 10 + c - '0';
			while ((c = read()) >= '0' && c <= '9');
			if (c == '.')
				while ((c = read()) >= '0' && c <= '9')
					ret += (c - '0') / (div *= 10);
			if (neg)
				return -ret;
			return ret;
		}
		private void fillBuffer() throws IOException {
			bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
			if (bytesRead == -1)
				buffer[0] = -1;
		}
		private byte read() {
			try{
				if (bufferPointer == bytesRead)
					fillBuffer();
				return buffer[bufferPointer++];
			} catch(IOException e) {
				throw new RuntimeException();
			}
		}
		public void close() throws IOException {
			if (din == null)
				return;
			din.close();
		}
	}
}


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

public class D {

    private void solution() throws IOException {
        int n = in.nextInt();
        int a = in.nextInt() - 1, b = in.nextInt() - 1;
        int[] g = new int[n - 1];
        for (int i = 0; i < n - 1; i++) {
            g[i] = in.nextInt();
        }
        int[] k = new int[n];
        for (int i = 0; i < n; i++) {
            k[i] = in.nextInt();
        }

        Map<Integer, Integer> mapL = new HashMap<>();
        Map<Integer, Integer> mapR = new HashMap<>();
        mapL.put(k[a], a);
        mapR.put(k[a], a);

        long[] s = new long[n];

        int l = a, r = a;
        int maxL = a, maxR = a;

        boolean move = true;
        while (move) {
            if (l == b) {
                out.println(s[l]);
                return;
            }
            if (r == b) {
                out.println(s[r]);
                return;
            }
            move = false;
            if (l - 1 >= 0) {
                if (mapL.containsKey(g[l - 1])) {
                    l--;
                    move = true;
                    s[l] = s[l + 1] + 1;
                    if (!mapL.containsKey(k[l])) {
                        mapL.put(k[l], l);
                    }
                } else if (mapR.containsKey(g[l - 1])) {
                    l--;
                    move = true;
                    int p = mapR.get(g[l]);
                    if (p > maxR) {
                        maxR = p;
                    }
                    s[l] = s[maxR] + Math.abs(maxR - l);
                    if (!mapL.containsKey(k[l])) {
                        mapL.put(k[l], l);
                    }
                }
            }
            if (r + 1 < n) {
                if (mapR.containsKey(g[r])) {
                    r++;
                    move = true;
                    s[r] = s[r - 1] + 1;
                    if (!mapR.containsKey(k[r])) {
                        mapR.put(k[r], r);
                    }
                } else if (mapL.containsKey(g[r])) {
                    r++;
                    move = true;
                    int p = mapL.get(g[r - 1]);
                    if (p < maxL) {
                        maxL = p;
                    }
                    s[r] = s[maxL] + Math.abs(maxL - r);
                    if (!mapR.containsKey(k[r])) {
                        mapR.put(k[r], r);
                    }
                }
            }
        }
        out.println(-1);
    }

    private void run() throws IOException {
        in = new Scanner(System.in);
        out = new PrintWriter(System.out);
        solution();
        in.close();
        out.close();
    }

    private Scanner in;
    private PrintWriter out;

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

    private class Scanner {

        BufferedReader br;
        StringTokenizer st;

        private Scanner(InputStream is) {
            br = new BufferedReader(new InputStreamReader(is));
        }

        private String next() throws IOException {
            while (st == null || !st.hasMoreTokens()) {
                st = new StringTokenizer(br.readLine());
            }
            return st.nextToken();
        }

        private Integer nextInt() throws IOException {
            return Integer.parseInt(next());
        }

        private Long nextLong() throws IOException {
            return Long.parseLong(next());
        }

        private Double nextDouble() throws IOException {
            return Double.parseDouble(next());
        }

        private void close() throws IOException {
            st = null;
            br.close();
        }
    }
}


import java.io.BufferedReader;
// import java.io.FileInputStream;
// import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;

import static java.lang.Math.*;
import static java.util.Arrays.copyOf;
import static java.util.Arrays.fill;
import static java.util.Arrays.sort;
import static java.util.Collections.reverse;
import static java.util.Collections.reverseOrder;
import static java.util.Collections.sort;

public class Main {
    private FastScanner in;
    private PrintWriter out;

    private void solve() throws IOException {
        int n = in.nextInt(), a = in.nextInt(), b = in.nextInt();

        int[] g = new int[n];
        for (int i = 1; i < n; i++)
            g[i] = in.nextInt();

        int[] k = new int[n + 1];
        for (int i = 1; i <= n; i++)
            k[i] = in.nextInt();

        if (a < b) {
            a = n - a + 1;
            b = n - b + 1;

            for (int i = 1, j = n - 1, x; i < j; i++, j--) {
                x = g[i];
                g[i] = g[j];
                g[j] = x;
            }

            for (int i = 1, j = n, x; i < j; i++, j--) {
                x = k[i];
                k[i] = k[j];
                k[j] = x;
            }
        }

        int[] l = new int[n + 1];
        HashSet<Integer> set = new HashSet<>();
        set.add(k[a]);
        l[a] = a;

        for (int cur = a, r = a; cur > b; ) {

            while (!set.contains(g[cur - 1]))
                if (r < n && set.contains(g[r]))
                    set.add(k[++r]);
                else
                    break;

            if (set.contains(g[cur - 1])) {
                l[--cur] = r;
                set.add(k[cur]);
            } else
                break;
        }

        if (l[b] == 0) {
            out.println(-1);
            return;
        }

        int[] r = new int[n + 1];
        set.clear();
        set.add(k[a]);
        r[a] = a;

        for (int cur = a, le = a; cur < l[b]; ) {

            while (!set.contains(g[cur]))
                if (le > 1 && set.contains(g[le - 1]))
                    set.add(k[--le]);
                else
                    break;

            if (set.contains(g[cur])) {
                r[++cur] = le;
                set.add(k[cur]);
            } else
                break;
        }

        long ans = 0;
        for (int cur = b; cur != a; ) {
            if (cur < a) {
                ans += l[cur] - cur;
                cur = l[cur];
            } else {
                ans += cur - r[cur];
                cur = r[cur];
            }
        }
        out.println(ans);
    }

    class FastScanner {
        StringTokenizer st;
        BufferedReader br;

        FastScanner(InputStream s) {
            br = new BufferedReader(new InputStreamReader(s));
        }

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

        boolean hasNext() throws IOException {
            return br.ready() || (st != null && st.hasMoreTokens());
        }

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

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

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

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

        boolean hasNextLine() throws IOException {
            return br.ready();
        }
    }

    private void run() throws IOException {
        in = new FastScanner(System.in); // new FastScanner(new FileInputStream(".in"));
        out = new PrintWriter(System.out); // new PrintWriter(new FileOutputStream(".out"));

        solve();

        out.flush();
        out.close();
    }

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


import java.io.*;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;

public class D {

    private void solution() throws IOException {
        int n = in.nextInt();
        int a = in.nextInt() - 1, b = in.nextInt() - 1;
        int[] g = new int[n - 1];
        for (int i = 0; i < n - 1; i++) {
            g[i] = in.nextInt();
        }
        int[] k = new int[n];
        for (int i = 0; i < n; i++) {
            k[i] = in.nextInt();
        }
        Set<Integer> L = new HashSet<>();
        Set<Integer> R = new HashSet<>();
        L.add(k[a]);
        R.add(k[a]);
        long[] s = new long[n];
        int l = a, r = a;
        for (int i = 0; i < 4 * n; i++) {
            Set<Integer> tempL = new HashSet<>();
            if (l - 1 >= 0) {
                if (L.contains(g[l - 1])) {
                    tempL.add(k[l - 1]);
                    s[l - 1] += s[l] + 1;
                } else if (R.contains(g[l - 1])) {
                    tempL.addAll(R);
                    tempL.add(k[l - 1]);
                    s[l - 1] += s[r] + (r - l) + 1;
                }
            }

            Set<Integer> tempR = new HashSet<>();
            if (r + 1 < n) {
                if (R.contains(g[r])) {
                    tempR.add(k[r + 1]);
                    s[r + 1] += s[r] + 1;
                } else if (L.contains(g[r])) {
                    tempR.addAll(L);
                    tempR.add(k[r + 1]);
                    s[r + 1] += s[l] + (r - l) + 1;
                }
            }

            boolean move = false;
            if (tempL.size() > 0) {
                l--;
                L.addAll(tempL);
                move = true;
            }
            if (tempR.size() > 0) {
                r++;
                R.addAll(tempR);
                move = true;
            }
            if (!move) {
                out.print(-1);
                return;
            }
            if (l == b) {
                out.println(s[l]);
                return;
            }
            if (r == b) {
                out.println(s[r]);
                return;
            }
        }
    }

    private void run() throws IOException {
        in = new Scanner(System.in);
        out = new PrintWriter(System.out);
        solution();
        in.close();
        out.close();
    }

    private Scanner in;
    private PrintWriter out;

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

    private class Scanner {

        BufferedReader br;
        StringTokenizer st;

        private Scanner(InputStream is) {
            br = new BufferedReader(new InputStreamReader(is));
        }

        private String next() throws IOException {
            while (st == null || !st.hasMoreTokens()) {
                st = new StringTokenizer(br.readLine());
            }
            return st.nextToken();
        }

        private Integer nextInt() throws IOException {
            return Integer.parseInt(next());
        }

        private Long nextLong() throws IOException {
            return Long.parseLong(next());
        }

        private Double nextDouble() throws IOException {
            return Double.parseDouble(next());
        }

        private void close() throws IOException {
            st = null;
            br.close();
        }
    }
}


//package ecr012;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

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

	public static int[] sieveEratosthenes(int n) {
		if (n <= 32) {
			int[] primes = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31 };
			for (int i = 0; i < primes.length; i++) {
				if (n < primes[i]) {
					return Arrays.copyOf(primes, i);
				}
			}
			return primes;
		}

		int u = n + 32;
		double lu = Math.log(u);
		int[] ret = new int[(int) (u / lu + u / lu / lu * 1.5)];
		ret[0] = 2;
		int pos = 1;

		int[] isnp = new int[(n + 1) / 32 / 2 + 1];
		int sup = (n + 1) / 32 / 2 + 1;

		int[] tprimes = { 3, 5, 7, 11, 13, 17, 19, 23, 29, 31 };
		for (int tp : tprimes) {
			ret[pos++] = tp;
			int[] ptn = new int[tp];
			for (int i = (tp - 3) / 2; i < tp << 5; i += tp)
				ptn[i >> 5] |= 1 << (i & 31);
			for (int j = 0; j < sup; j += tp) {
				for (int i = 0; i < tp && i + j < sup; i++) {
					isnp[j + i] |= ptn[i];
				}
			}
		}

		// 3,5,7
		// 2x+3=n
		int[] magic = { 0, 1, 23, 2, 29, 24, 19, 3, 30, 27, 25, 11, 20, 8, 4, 13, 31, 22, 28, 18, 26, 10, 7, 12, 21, 17,
				9, 6, 16, 5, 15, 14 };
		int h = n / 2;
		for (int i = 0; i < sup; i++) {
			for (int j = ~isnp[i]; j != 0; j &= j - 1) {
				int pp = i << 5 | magic[(j & -j) * 0x076be629 >>> 27];
				int p = 2 * pp + 3;
				if (p > n)
					break;
				ret[pos++] = p;
				if ((long) p * p > n)
					continue;
				for (int q = (p * p - 3) / 2; q <= h; q += p)
					isnp[q >> 5] |= 1 << q;
			}
		}

		return Arrays.copyOf(ret, pos);
	}

	int[] primes = sieveEratosthenes(400000);

	void solve()
	{
		long n = nl();
		long ans = 0;
		if(n <= 10) {
			if(n >= 6)ans++;
			if(n >= 8)ans++;
			if(n >= 10)ans++;
			out.println(ans);
			return;
		}

		MeisselLehmer2 ml = new MeisselLehmer2(n/2);
		for(int i = 0;i < primes.length;i++) {
			long plus = ml.pi(n/primes[i]) - (i+1);
			if(plus <= 0)break;
			ans += plus;
		}

		for(int p : primes) {
			if((long)p*p*p <= n) {
				ans++;
			}else {
				break;
			}
		}
		out.println(ans);
	}

	public static class MeisselLehmer2 {
		int[] primes;
//		int[] cump;
		int[] xcums;
		long[] isp;

		int cachelimit;
//		Map<Long, Long> picache;
//		Map<Long, Long> phicache;
		LongHashCounterL picache;
		LongHashCounterL phicache;
		boolean cachePhi = false;

		int[][] cumps;
//		int[] FP = {2,3,5,7,11,13,17};
		int[] FP = {2,3,5,7,11,13,17,19};
		int M = FP.length;

		int B = 100;
		// 10^14 -> 200
		// 10^14/8 -> 100~200

		public MeisselLehmer2(long n)
		{
			assert n >= 4;
//			picache = new HashMap<>();
//			phicache = new HashMap<>();
			picache = new LongHashCounterL();
			phicache = new LongHashCounterL();

			int s = (int)Math.sqrt(n)*B; // not overflow!
			cachelimit = s;
			this.primes = sieveEratosthenes(s);
			xcums = new int[(s>>>6)+1];
			isp = new long[(s>>>6)+1];
			for(int p : primes)isp[p>>>6] |= 1L<<p;
			for(int i = 0;i < xcums.length-1;i++)xcums[i+1] = xcums[i] + Long.bitCount(isp[i]);

			cumps = new int[M][];
			boolean[] b = {true};
			int len = 1;
			for(int i = 0;i < M;i++){
				len *= FP[i];
				boolean[] c = new boolean[len];
				for(int j = 0;j < FP[i];j++){
					System.arraycopy(b, 0, c, j*b.length, b.length);
				}
				for(int k = 0;k < len;k+=FP[i])c[k] = false;
				cumps[i] = new int[len+1];
				for(int j = 0;j < len;j++)cumps[i][j+1] = cumps[i][j] + (c[j] ? 1 : 0);
				FP[i] = len;
				b = c;
			}
		}

		private long sqrt(long n)
		{
			long i = Math.max(0, (long)Math.sqrt(n)-2);
			while(i*i <= n)i++;
			return i-1;
		}

		private long cbrt(long n)
		{
			long i = Math.max(0, (long)Math.cbrt(n)-2);
			while(i*i*i <= n)i++;
			return i-1;
		}

		public long pi(long x)
		{
			if(x <= cachelimit){
				int ix = (int)x;
				return xcums[ix>>>6] + Long.bitCount(isp[ix>>>6]<<~ix);
//				return cump[(int)x];
			}
			if(picache.containsKey(x))return picache.get(x);

			int A = (int)pi(sqrt(sqrt(x)));
			long ret = A + phi(x, A) - P2(x, A) - P3(x, A) - 1;
			picache.put(x, ret);
			return ret;
		}

		private long phi(long x, int A)
		{
			if(A > 0 && A-1 < M){
				return cumps[A-1][FP[A-1]] * (x/FP[A-1]) + cumps[A-1][(int)(x%FP[A-1]+1)];
			}
			if(A > 0 && x <= (long)primes[A-1]*primes[A-1]){
				return pi(x) - A + 1;
			}
//			long code = x<<13|A;
//			if(phicache.containsKey(code))return phicache.get(code);

			long ret = x;
			for(int i = A-1;i >= 0;i--)ret -= phi(x/primes[i], i);

//			if(cachePhi)phicache.put(code, ret);
			return ret;
		}

		private long P2(long x, int A)
		{
			int B = (int)pi(sqrt(x));
			long ret = 0;
			for(int i = A;i < B;i++){
				ret += pi(x/primes[i]);
			}
			ret -= (long)(B-A)*(B+A-1)/2;
			return ret;
		}

		private long P3(long x, int A)
		{
			int C = (int)pi(cbrt(x));
			long ret = 0;
			for(int i = A;i < C;i++){
				long xi = x/primes[i];
				int B = (int)pi(sqrt(xi));
				for(int j = i;j < B;j++){
					ret += pi(xi/primes[j]) - j;
				}
			}
			return ret;
		}

		public static int[] sieveEratosthenes(int n) {
			if (n <= 32) {
				int[] primes = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31 };
				for (int i = 0; i < primes.length; i++) {
					if (n < primes[i]) {
						return Arrays.copyOf(primes, i);
					}
				}
				return primes;
			}

			int u = n + 32;
			double lu = Math.log(u);
			int[] ret = new int[(int) (u / lu + u / lu / lu * 1.5)];
			ret[0] = 2;
			int pos = 1;

			int[] isnp = new int[(n + 1) / 32 / 2 + 1];
			int sup = (n + 1) / 32 / 2 + 1;

			int[] tprimes = { 3, 5, 7, 11, 13, 17, 19, 23, 29, 31 };
			for (int tp : tprimes) {
				ret[pos++] = tp;
				int[] ptn = new int[tp];
				for (int i = (tp - 3) / 2; i < tp << 5; i += tp)
					ptn[i >> 5] |= 1 << (i & 31);
				for (int j = 0; j < sup; j += tp) {
					for (int i = 0; i < tp && i + j < sup; i++) {
						isnp[j + i] |= ptn[i];
					}
				}
			}

			// 3,5,7
			// 2x+3=n
			int[] magic = { 0, 1, 23, 2, 29, 24, 19, 3, 30, 27, 25, 11, 20, 8, 4, 13, 31, 22, 28, 18, 26, 10, 7, 12, 21, 17,
					9, 6, 16, 5, 15, 14 };
			int h = n / 2;
			for (int i = 0; i < sup; i++) {
				for (int j = ~isnp[i]; j != 0; j &= j - 1) {
					int pp = i << 5 | magic[(j & -j) * 0x076be629 >>> 27];
					int p = 2 * pp + 3;
					if (p > n)
						break;
					ret[pos++] = p;
					if ((long) p * p > n)
						continue;
					for (int q = (p * p - 3) / 2; q <= h; q += p)
						isnp[q >> 5] |= 1 << q;
				}
			}

			return Arrays.copyOf(ret, pos);
		}

		private static class LongHashCounterL {
			public long[] keys;
			public long[] allocated;
			private int scale = 1<<2;
			private int rscale = 1<<1;
			private int mask = scale-1;
			public int size = 0;

			public LongHashCounterL(){
				allocated = new long[scale];
				Arrays.fill(allocated, NG);
				keys = new long[scale];
			}

			// if value is NG, entry is removed. (e.g. 0)
			private static final int NG = 0;

			public boolean containsKey(long x)
			{
				int pos = h(x)&mask;
				while(allocated[pos] != NG){
					if(x == keys[pos])return true;
					pos = pos+1&mask;
				}
				return false;
			}

			public long get(long x)
			{
				int pos = h(x)&mask;
				while(allocated[pos] != NG){
					if(x == keys[pos])return allocated[pos];
					pos = pos+1&mask;
				}
				return NG;
			}

			public long put(long x, long v)
			{
				int pos = h(x)&mask;
				while(allocated[pos] != NG){
					if(x == keys[pos]){
						long oldval = allocated[pos];
						allocated[pos] = v;
						return oldval;
					}
					pos = pos+1&mask;
				}
				if(size == rscale){
					resizeAndPut(x, v);
				}else{
					keys[pos] = x;
					allocated[pos] = v;
				}
				size++;
				return 0;
			}

			public long inc(long x, long v)
			{
				int pos = h(x)&mask;
				while(allocated[pos] != NG){
					if(x == keys[pos]){
						allocated[pos] += v;
						return allocated[pos];
					}
					pos = pos+1&mask;
				}
				if(size == rscale){
					resizeAndPut(x, v);
				}else{
					keys[pos] = x;
					allocated[pos] = v;
				}
				size++;
				return v;
			}

			public boolean remove(long x)
			{
				int pos = h(x)&mask;
				while(allocated[pos] != NG){
					if(x == keys[pos]){
						size--;
						// take last and fill rmpos
						int last = pos;
						pos = pos+1&mask;
						while(allocated[pos] != NG){
							int lh = h(keys[pos])&mask;
							// lh <= last < pos
							if(
									lh <= last && last < pos ||
									pos < lh && lh <= last ||
									last < pos && pos < lh
									){
								keys[last] = keys[pos];
								allocated[last] = allocated[pos];
								last = pos;
							}
							pos = pos+1&mask;
						}
						keys[last] = 0;
						allocated[last] = NG;

						return true;
					}
					pos = pos+1&mask;
				}
				return false;
			}

			private void resizeAndPut(long x, long v)
			{
				int nscale = scale<<1;
				int nrscale = rscale<<1;
				int nmask = nscale-1;
				long[] nallocated = new long[nscale];
				Arrays.fill(nallocated, NG);
				long[] nkeys = new long[nscale];
				for(int i = next(0);i < scale;i = next(i+1)){
					long y = keys[i];
					int pos = h(y)&nmask;
					while(nallocated[pos] != NG)pos = pos+1&nmask;
					nkeys[pos] = y;
					nallocated[pos] = allocated[i];
				}
				{
					int pos = h(x)&nmask;
					while(nallocated[pos] != NG)pos = pos+1&nmask;
					nkeys[pos] = x;
					nallocated[pos] = v;
				}
				allocated = nallocated;
				keys = nkeys;
				scale = nscale;
				rscale = nrscale;
				mask = nmask;
			}

			public int next(int itr)
			{
				while(itr < scale && allocated[itr] == NG)itr++;
				return itr;
			}

			private int h(long x)
			{
				x ^= x>>>33;
				x *= 0xff51afd7ed558ccdL;
				x ^= x>>>33;
				x *= 0xc4ceb9fe1a85ec53L;
				x ^= x>>>33;
				return (int)x;
			}

			@Override
			public String toString()
			{
				StringBuilder sb = new StringBuilder();
				for(int i = next(0);i < scale;i = next(i+1)){
					sb.append(",");
					sb.append(keys[i] + ":" + allocated[i]);
				}
				return sb.length() == 0 ? "" : sb.substring(1);
			}
		}
	}

	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 F3().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)); }
}