import java.util.Map;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.InputMismatchException;
import java.util.TreeMap;
import java.util.Set;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.util.NavigableMap;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.Writer;
import java.util.SortedMap;
import java.io.InputStream;

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

class TaskE {

    static final int MOD = 1000000007;

    public void solve(int testNumber, FastScanner in, FastPrinter out) {
        int n = in.nextInt();
        int p = in.nextInt();
        NavigableMap<Integer, Integer> g = new TreeMap<Integer, Integer>();
        g.put(1, 0);
        g.put(3, 1);
        int lastG = 1;
        for (int d = 3; d < p - 1; ) {
            int a = d / 3;
            int b = d - d / 3;
            Integer na = g.higherKey(a);
            Integer nb = g.higherKey(b);
            long z1 = na * 3L;
            long z2 = 3L * nb / 2;
            while (z2 - z2 / 3 >= nb) {
                z2--;
            }
            while (z2 - z2 / 3 < nb) {
                ++z2;
            }
            long z = Math.min(z1, z2);
            if (z > p - 1) {
                break;
            }
            int zi = (int) z;
            int ga = g.get(g.floorKey(zi / 3));
            int gb = g.get(g.floorKey(zi - zi / 3));
            int ng = -1;
            for (int j = 0; j < 3; j++) {
                if (j == ga || j == gb) {
                    continue;
                }
                ng = j;
                break;
            }
            if (ng != lastG) {
                g.put(zi, ng);
            }
            lastG = ng;
            d = zi;
        }
        long[] count = new long[3];
        for (int i : g.keySet()) {
            Integer ni = g.higherKey(i);
            if (ni == null) {
                ni = p;
            }
            int first = p - i;
            int second = p - ni;
            count[g.get(i)] += s(second + 1, first + 1);
        }
        for (int i = 0; i < 3; i++) {
            count[i] %= MOD;
        }
        int[][] dp = new int[n + 1][4];
        dp[0][0] = 1;
        for (int i = 1; i <= n; i++) {
            for (int x = 0; x < 3; x++) {
                for (int y = 0; y < 4; y++) {
                    dp[i][x ^ y] = (int) ((dp[i][x ^ y] + (long) dp[i - 1][y] * count[x]) % MOD);
                }
            }
        }
        long ans = 0L + dp[n][1] + dp[n][2] + dp[n][3];
        out.println(ans % MOD);
    }

    static long s(int a, int b) {
        if (a >= b) {
            return 0;
        }
        --b;
        --a;
        long ret = ss(b) - ss(a);
        return ret;
    }

    static long ss(int n) {
        return (long) n * (n + 1) / 2;
    }
}

class FastScanner extends BufferedReader {

    boolean isEOF;

    public FastScanner(InputStream is) {
        super(new InputStreamReader(is));
    }

    public int read() {
        try {
            int ret = super.read();
            if (isEOF && ret < 0) {
                throw new InputMismatchException();
            }
            isEOF = ret == -1;
            return ret;
        } catch (IOException e) {
            throw new InputMismatchException();
        }
    }

    static boolean isWhiteSpace(int c) {
        return c >= -1 && c <= 32;
    }

    public int nextInt() {
        int c = read();
        while (isWhiteSpace(c)) {
            c = read();
        }
        int sgn = 1;
        if (c == '-') {
            sgn = -1;
            c = read();
        }
        int ret = 0;
        while (!isWhiteSpace(c)) {
            if (c < '0' || c > '9') {
                throw new NumberFormatException("digit expected " + (char) c
                        + " found");
            }
            ret = ret * 10 + c - '0';
            c = read();
        }
        return ret * sgn;
    }

    }

class FastPrinter extends PrintWriter {

    public FastPrinter(OutputStream out) {
        super(out);
    }

    public FastPrinter(Writer out) {
        super(out);
    }

}


import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.StringTokenizer;

public class CF273E {

    final static long mod = 1000000007;

    public static void solve(Input in, PrintWriter out) throws IOException {
        int n = in.nextInt();
        int p = in.nextInt();
        ArrayList<Long> starts = new ArrayList<Long>();
        ArrayList<Integer> gs = new ArrayList<Integer>();
        starts.add(0L);
        gs.add(0);
        starts.add(3L);
        gs.add(1);
        long u = 3, v = 1;
        for (int j1 = 0, j2 = 0; u < p; ) {
            while (starts.get(j1 + 1) <= u / 3) {
                ++j1;
            }
            while (starts.get(j2 + 1) <= u - u / 3) {
                ++j2;
            }
            long next1 = starts.get(j1 + 1) * 3;
            if (next1 / 3 < starts.get(j1 + 1) || (next1 - 1) / 3 >= starts.get(j1 + 1)) {
                throw new AssertionError();
            }
            long next2 = (starts.get(j2 + 1) * 3) / 2;
            while (next2 - next2 / 3 < starts.get(j1 + 1)) {
                next2++;
            }
            while (next2 - 1 - (next2 - 1) / 3 >= starts.get(j2 + 1)) {
                next2--;
            }
            if (next2 - next2 / 3 < starts.get(j2 + 1) || next2 - 1 - (next2 - 1) / 3 >= starts.get(j2 + 1)) {
                throw new AssertionError();
            }
            long next = Math.min(next1, next2);
            int val = mutex(gs.get(next >= next1 ? j1 + 1 : j1), gs.get(next >= next2 ? j2 + 1 : j2));
            if (val != v) {
                starts.add(next);
                gs.add(val);
            }
            u = next;
            v = val;
        }
//        System.err.println(starts.size());
        long[] c = new long[3];
        for (int i = 0; i < starts.size(); ++i) {
            long from = starts.get(i);
            long to = i == starts.size() - 1 ? p - 1 : starts.get(i + 1) - 1;
            if (to >= p) {
                to = p - 1;
            }
            if (from > to) {
                continue;
            }
//            System.err.println(from + " " + to + " " + gs.get(i));
//            System.err.println((to - from + 1) * p);
//            System.err.println(to * (to + 1) / 2);
//            System.err.println((from - 1) * (from) / 2);
            c[gs.get(i)] = (c[gs.get(i)] + (to - from + 1) * p) % mod;
            c[gs.get(i)] = (c[gs.get(i)] + mod - (to * (to + 1) / 2 % mod)) % mod;
            c[gs.get(i)] = (c[gs.get(i)] + (from - 1) * (from) / 2) % mod;
        }
        c[0] = (c[0] + mod - p) % mod;
//        for (int i = 1; i < p; ++i) {
//            c[g[i]] = (c[g[i]] + p - i) % mod;
//        }
        long[] d = new long[4];
        d[0] = 1;
        for (int it = 0; it < n; ++it) {
            long[] dd = new long[4];
            for (int i = 0; i < 4; ++i) {
                for (int j = 0; j < 3; ++j) {
                    dd[i ^ j] = (dd[i ^ j] + d[i] * c[j]) % mod;
                }
            }
            d = dd;
        }
        long ans = (d[1] + d[2] + d[3]) % mod;
        out.println(ans);
    }

    private static int mutex(int a, int b) {
        if (a != 0 && b != 0) return 0;
        if (a != 1 && b != 1) return 1;
        return 2;
    }

    public static void main(String[] args) throws IOException {
        PrintWriter out = new PrintWriter(System.out);
        solve(new Input(new BufferedReader(new InputStreamReader(System.in))), out);
        out.close();
    }

    static class Input {
        BufferedReader in;
        StringTokenizer st;

        public Input(BufferedReader in) {
            this.in = in;
            eat("");
        }

        public Input(String s) {
            this.in = new BufferedReader(new StringReader(s));
        }

        public void eat(String str) {
            st = new StringTokenizer(str);
        }

        public String next() throws IOException {
            while (!st.hasMoreTokens()) {
                String line = in.readLine();
                if (line == null) {
                    return null;
                }
                eat(line);
            }
            return st.nextToken();
        }

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

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

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


import java.io.PrintStream;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.SortedMap;
import java.util.Map;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.TreeMap;
import java.util.InputMismatchException;
import java.util.Set;
import java.util.NavigableMap;
import java.io.Reader;
import java.io.InputStream;

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

class TaskE {

    static int[] g;
    static int MAXN = 1000;

    static {
        g = new int[MAXN];
        for (int i = 3; i < g.length; i++) {
            int g1 = g[i / 3];
            int g2 = g[i - i / 3];
            for (int j = 0; j < 3; j++) {
                if (g1 == j || g2 == j) {
                    continue;
                }
                g[i] = j;
                break;
            }
            System.out.print(g[i]);
        }
        System.out.println();
        for (int i = 3; i < g.length; i++) {
            System.out.print(i % 10);
        }
    }

    static final int MOD = 1000000007;

    public void solve(int testNumber, FastScanner in, FastPrinter out) {
        int n = in.nextInt();
        int p = in.nextInt();
        NavigableMap<Integer, Integer> g = new TreeMap<Integer, Integer>();
        g.put(1, 0);
        g.put(3, 1);
        for (int d = 3; d < p - 1; ) {
            int a = d / 3;
            int b = d - d / 3;
            Integer na = g.higherKey(a);
            Integer nb = g.higherKey(b);
            if (na == null || nb == null) {
                throw new AssertionError();
            }
            long z1 = na * 3L;
            long z2 = 3L * nb / 2;
            while (z2 - z2 / 3 >= nb) {
                z2--;
            }
            while (z2 - z2 / 3 < nb) {
                ++z2;
            }
            long z = Math.min(z1, z2);
            if (z > p - 1) {
                break;
            }
            int zi = (int) z;
            int ga = g.get(g.floorKey(zi / 3));
            int gb = g.get(g.floorKey(zi - zi / 3));
            int ng = -1;
            for (int j = 0; j < 3; j++) {
                if (j == ga || j == gb) {
                    continue;
                }
                ng = j;
                break;
            }
            g.put(zi, ng);
            d = zi;
        }
        long[] count = new long[3];
        for (int i : g.keySet()) {
            Integer ni = g.higherKey(i);
            if (ni == null) {
                ni = p;
            }
            int first = p - i;
            int second = p - ni;
            count[g.get(i)] += s(second + 1, first + 1);
        }
        for (int i = 0; i < 3; i++) {
            count[i] %= MOD;
        }
        int[][] dp = new int[n + 1][4];
        dp[0][0] = 1;
        for (int i = 1; i <= n; i++) {
            for (int x = 0; x < 3; x++) {
                for (int y = 0; y < 4; y++) {
                    dp[i][x ^ y] = (int) ((dp[i][x ^ y] + (long) dp[i - 1][y] * count[x]) % MOD);
                }
            }
        }
        long ans = 0L + dp[n][1] + dp[n][2] + dp[n][3];
        out.println(ans % MOD);
    }

    static long s(int a, int b) {
        if (a >= b) {
            return 0;
        }
        --b;
        --a;
        long ret = ss(b) - ss(a);
        return ret;
    }

    static long ss(int n) {
        return (long) n * (n + 1) / 2;
    }
}

class FastScanner extends BufferedReader {

    boolean isEOF;

    public FastScanner(InputStream is) {
        super(new InputStreamReader(is));
    }

    public int read() {
        try {
            int ret = super.read();
            if (isEOF && ret < 0) {
                throw new InputMismatchException();
            }
            isEOF = ret == -1;
            return ret;
        } catch (IOException e) {
            throw new InputMismatchException();
        }
    }

    static boolean isWhiteSpace(int c) {
        return c >= -1 && c <= 32;
    }

    public int nextInt() {
        int c = read();
        while (isWhiteSpace(c)) {
            c = read();
        }
        int sgn = 1;
        if (c == '-') {
            sgn = -1;
            c = read();
        }
        int ret = 0;
        while (!isWhiteSpace(c)) {
            if (c < '0' || c > '9') {
                throw new NumberFormatException("digit expected " + (char) c
                        + " found");
            }
            ret = ret * 10 + c - '0';
            c = read();
        }
        return ret * sgn;
    }

    }

class FastPrinter extends PrintWriter {

    public FastPrinter(OutputStream out) {
        super(out);
    }

    public FastPrinter(Writer out) {
        super(out);
    }

}


import java.util.Map;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.InputMismatchException;
import java.util.TreeMap;
import java.util.Set;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.util.NavigableMap;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.Writer;
import java.util.SortedMap;
import java.io.InputStream;

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

class TaskE {

    static final int MOD = 1000000007;

    public void solve(int testNumber, FastScanner in, FastPrinter out) {
        int n = in.nextInt();
        int p = in.nextInt();
        NavigableMap<Integer, Integer> g = new TreeMap<Integer, Integer>();
        g.put(1, 0);
        g.put(3, 1);
        for (int d = 3; d < p - 1; ) {
            int a = d / 3;
            int b = d - d / 3;
            Integer na = g.higherKey(a);
            Integer nb = g.higherKey(b);
            if (na == null || nb == null) {
                throw new AssertionError();
            }
            long z1 = na * 3L;
            long z2 = 3L * nb / 2;
            while (z2 - z2 / 3 >= nb) {
                z2--;
            }
            while (z2 - z2 / 3 < nb) {
                ++z2;
            }
            long z = Math.min(z1, z2);
            if (z > p - 1) {
                break;
            }
            int zi = (int) z;
            int ga = g.get(g.floorKey(zi / 3));
            int gb = g.get(g.floorKey(zi - zi / 3));
            int ng = -1;
            for (int j = 0; j < 3; j++) {
                if (j == ga || j == gb) {
                    continue;
                }
                ng = j;
                break;
            }
            g.put(zi, ng);
            d = zi;
        }
        long[] count = new long[3];
        for (int i : g.keySet()) {
            Integer ni = g.higherKey(i);
            if (ni == null) {
                ni = p;
            }
            int first = p - i;
            int second = p - ni;
            count[g.get(i)] += s(second + 1, first + 1);
        }
        for (int i = 0; i < 3; i++) {
            count[i] %= MOD;
        }
        int[][] dp = new int[n + 1][4];
        dp[0][0] = 1;
        for (int i = 1; i <= n; i++) {
            for (int x = 0; x < 3; x++) {
                for (int y = 0; y < 4; y++) {
                    dp[i][x ^ y] = (int) ((dp[i][x ^ y] + (long) dp[i - 1][y] * count[x]) % MOD);
                }
            }
        }
        long ans = 0L + dp[n][1] + dp[n][2] + dp[n][3];
        out.println(ans % MOD);
    }

    static long s(int a, int b) {
        if (a >= b) {
            return 0;
        }
        --b;
        --a;
        long ret = ss(b) - ss(a);
        return ret;
    }

    static long ss(int n) {
        return (long) n * (n + 1) / 2;
    }
}

class FastScanner extends BufferedReader {

    boolean isEOF;

    public FastScanner(InputStream is) {
        super(new InputStreamReader(is));
    }

    public int read() {
        try {
            int ret = super.read();
            if (isEOF && ret < 0) {
                throw new InputMismatchException();
            }
            isEOF = ret == -1;
            return ret;
        } catch (IOException e) {
            throw new InputMismatchException();
        }
    }

    static boolean isWhiteSpace(int c) {
        return c >= -1 && c <= 32;
    }

    public int nextInt() {
        int c = read();
        while (isWhiteSpace(c)) {
            c = read();
        }
        int sgn = 1;
        if (c == '-') {
            sgn = -1;
            c = read();
        }
        int ret = 0;
        while (!isWhiteSpace(c)) {
            if (c < '0' || c > '9') {
                throw new NumberFormatException("digit expected " + (char) c
                        + " found");
            }
            ret = ret * 10 + c - '0';
            c = read();
        }
        return ret * sgn;
    }

    }

class FastPrinter extends PrintWriter {

    public FastPrinter(OutputStream out) {
        super(out);
    }

    public FastPrinter(Writer out) {
        super(out);
    }

}


import static java.lang.Double.parseDouble;
import static java.lang.Integer.parseInt;
import static java.lang.Long.parseLong;
import static java.lang.System.exit;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.StringTokenizer;

public class F {

	static BufferedReader in;
	static PrintWriter out;
	static StringTokenizer tok;

	static void solve() throws Exception {
		int n = nextInt();
		int d = nextInt();
		int mod = nextInt();
		if (n == 1) {
			out.print('1');
			return;
		}
		int fracs[] = new int[d + 2];
		for (int i = 1; i < fracs.length; i++) {
			fracs[i] = BigInteger.valueOf(i).modInverse(BigInteger.valueOf(mod)).intValue();
		}
		int maxsize = n;
		int cnts[] = new int[maxsize + 1];
		cnts[1] = 1;
		int cnts2[][][] = new int[maxsize + 1][d + 1][maxsize + 1];
		cnts2[0][0][1] = 1;
		for (int lastsize = 0; lastsize < (n - 1) / 2; lastsize++) {
			int nlastsize = lastsize + 1;
			int ccnt = cnts[nlastsize];
			int ccnt2[][] = cnts2[lastsize];
			int ncnt2[][] = cnts2[nlastsize];
			for (int ctrees = 0; ctrees <= d; ctrees++) {
				for (int csize = 1; csize <= maxsize; csize++) {
					int cur = ccnt2[ctrees][csize];
//					if (cur != 0) {
//						System.err.println(csize + " " + ctrees + " " + lastsize + " -> " + cur);
//					}
					for (int i = 0, ntrees = ctrees, nsize = csize;
						ntrees <= d && nsize <= maxsize;
						++i, ++ntrees, nsize += nlastsize) {
						ncnt2[ntrees][nsize] += cur;
						if (ncnt2[ntrees][nsize] >= mod) {
							ncnt2[ntrees][nsize] -= mod;
						}
						cur = (int) ((long) cur * (ccnt + i) % mod * fracs[i + 1] % mod);
					}
				}
			}
			if (nlastsize + 1 <= maxsize) {
				cnts[nlastsize + 1] = ncnt2[d - 1][nlastsize + 1];
			}
		}
		int ans = 0;
		if (n % 2 == 0) {
			ans = (int) ((long) cnts[n / 2] * (cnts[n / 2] + 1) % mod * fracs[2] % mod);
		}
		ans = (ans + cnts2[(n - 1) / 2][d][n]) % mod;
		out.print(ans);
	}

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

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

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

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

	public static void main(String[] args) {
		try {
			in = new BufferedReader(new InputStreamReader(System.in));
			out = new PrintWriter(new OutputStreamWriter(System.out));
			solve();
			in.close();
			out.close();
		} catch (Throwable e) {
			e.printStackTrace();
			exit(1);
		}
	}
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.math.BigInteger;
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
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskH solver = new TaskH();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskH {
        long[] lens;
        Description[] cache;
        int m;
        int[] b;
        int[] gen;

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            int d = in.nextInt();
            m = in.nextInt();
            gen = new int[d];
            for (int i = 0; i < d; ++i) gen[i] = in.nextInt();
            int blen = in.nextInt();
            b = new int[blen];
            for (int i = 0; i < blen; ++i) {
                b[i] = in.nextInt();
            }
            long left = in.nextLong();
            long right = in.nextLong();
            lens = new long[100];
            long len = 1;
            int layer = 0;
            lens[layer] = len;
            while (true) {
                ++layer;
                if (len < (right + d - 1) / d) {
                    len *= d;
                    lens[layer] = len;
                } else {
                    lens[layer] = right + 1;
                    break;
                }
            }
            cache = new Description[layer + 1];
            Description d1 = describe(layer, right);
            Description d2 = describe(layer, left + b.length - 2);
            long res = d1.matchesInside[0] - d2.matchesInside[0];
            out.println(res);
        }

        private Description describe(int layer, long upto) {
            if (upto > lens[layer]) throw new RuntimeException();
            if (upto == lens[layer]) {
                if (cache[layer] != null) return cache[layer];
            }
            Description res = null;
            if (upto <= 0) {
                res = new Description(upto);
                return res;
            }
            if (layer == 0) {
                res = new Description(upto);
                for (int shift = 0; shift < m; ++shift) {
                    if (b.length > 1 && b[0] >= shift) {
                        res.matchesPrefix[shift] = BigInteger.ONE;
                    } else {
                        res.matchesPrefix[shift] = BigInteger.ZERO;
                    }
                    if (b.length > 1 && b[b.length - 1] >= shift) {
                        res.matchesSuffix[shift] = BigInteger.ONE.shiftLeft(b.length - 1);
                    } else {
                        res.matchesSuffix[shift] = BigInteger.ZERO;
                    }
                    if (b.length == 1 && b[0] >= shift) {
                        ++res.matchesInside[shift];
                    }
                    byte[] bits = new byte[(b.length + 7) >> 3];
                    for (int i = 0; i < b.length; ++i) {
                        if (b[i] >= shift) {
                            bits[bits.length - 1 - (i >> 3)] |= (1 << (i & 7));
                        }
                    }
                    res.coveredIfStartsFrom[shift] = new BigInteger(1, bits);
                }
            } else {
                long togo = upto;
                for (int i = 0; i < gen.length && togo > 0; ++i) {
                    long by = Math.min(togo, lens[layer - 1]);
                    Description d = describe(layer - 1, by);
                    res = combine(res, d, gen[i]);
                    togo -= by;
                }
            }
            if (res == null) throw new RuntimeException();
            if (upto == lens[layer]) {
                cache[layer] = res;
            }
            return res;
        }

        private Description combine(Description a, Description b, int delta) {
            if (a == null) {
                if (delta != 0) throw new RuntimeException();
                return b;
            }
            Description res = new Description(a.len + b.len);
            for (int shift = 0; shift < m; ++shift) {
                int ashift = shift;
                int bshift = (shift + delta) % m;
                res.matchesInside[shift] = a.matchesInside[ashift] + b.matchesInside[bshift];
                res.matchesInside[shift] += a.matchesPrefix[ashift].and(b.matchesSuffix[bshift].shiftRight(1)).bitCount();
                res.matchesPrefix[shift] = b.matchesPrefix[bshift];
                if (b.len < this.b.length) {
                    res.matchesPrefix[shift] = res.matchesPrefix[shift].or(a.matchesPrefix[ashift].and(b.coveredIfStartsFrom[bshift].shiftRight(1)).shiftLeft((int) b.len));
                }
                res.matchesSuffix[shift] = a.matchesSuffix[ashift];
                if (a.len < this.b.length) {
                    res.matchesSuffix[shift] = res.matchesSuffix[shift].or(b.matchesSuffix[bshift].shiftRight((int) a.len).and(a.coveredIfStartsFrom[ashift]));
                }
                if (a.len < this.b.length) {
                    res.coveredIfStartsFrom[shift] = a.coveredIfStartsFrom[ashift].and(b.coveredIfStartsFrom[bshift].shiftRight((int) a.len));
                } else {
                    res.coveredIfStartsFrom[shift] = BigInteger.ZERO;
                }
            }
            return res;
        }

        class Description {
            long len;
            long[] matchesInside = new long[m];
            BigInteger[] matchesPrefix = new BigInteger[m];
            BigInteger[] matchesSuffix = new BigInteger[m];
            BigInteger[] coveredIfStartsFrom = new BigInteger[m];

            public Description(long len) {
                this.len = len;
            }

        }

    }

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

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

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

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

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

    }
}


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.util.HashMap;
import java.util.InputMismatchException;
import java.io.IOException;
import java.util.ArrayList;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author lewin
 */
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);
        TaskH solver = new TaskH();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskH {
        long all;
        int d;
        int m;
        int[] gen;
        int bits = 8;
        int sections;
        HashMap<Long, Long>[][] mp;

        public void solve(int testNumber, InputReader in, OutputWriter out) {
            d = in.nextInt();
            m = in.nextInt();
            sections = (m + bits - 1) / bits;
            all = (1L << m) - 1;
            gen = in.readIntArray(d);
            int n = in.nextInt();
            ArrayList<Long> masks = new ArrayList<>();
            for (int i = 0; i < n; i++) {
                masks.add((1L << (in.nextInt() + 1)) - 1);
            }
            long l = in.nextLong(), r = in.nextLong();
            l-=1;
            r-=1;
            mp = new HashMap[sections][1 << bits];
            for (int i = 0; i < sections; i++) for (int j = 0; j < 1 << bits; j++) mp[i][j] = new HashMap<>();
            out.println(count(masks, r + 2 - n) - count(masks, l));
        }

        long rotateRight(long x, int distance) {
            return ((x >> distance) | ((x & ((1L << distance) - 1)) << (m - distance)));
        }

        ArrayList<int[]> getNext(int shift, int section, int mask) {
            long cmask = mask;
            cmask <<= (long) section * bits;
            cmask = rotateRight(cmask, shift);
            ArrayList<int[]> ret = new ArrayList<>();
            for (int i = 0; i < sections; i++) {
                int csec = (int) (cmask & ((1 << bits) - 1));
                if (csec != 0) {
                    ret.add(new int[]{i, csec});
                }
                cmask >>= bits;
            }
            return ret;
        }

        long count(int section, int mask, long mx) {
            if (mx == 0) return 0;
            if (mx == 1) {
                return (section == 0 && ((mask & 1) == 1)) ? 1 : 0;
            }
            Long r = mp[section][mask].get(mx);
            if (r != null) return r;
            long bd = 1;
            while (bd < (mx + d - 1) / d) bd *= d;

            long ans = 0;
            for (int i = 0; i < (mx + bd - 1) / bd; i++) {
                long nmx = (i == (mx + bd - 1) / bd - 1) ? ((mx - 1) % bd + 1) : bd;
                for (int[] x : getNext(gen[i], section, mask)) {
                    ans += count(x[0], x[1], nmx);
                }
            }
            mp[section][mask].put(mx, ans);
            return ans;
        }

        long count(ArrayList<Long> masks, long mx) {
            if (masks.size() == 1) {
                long ans = 0;
                long mask = masks.get(0);
                for (int j = 0; j < sections; j++) {
                    ans += count(j, (int) (mask & ((1 << bits) - 1)), mx);
                    mask >>= bits;
                }
                return ans;
            }
            long ans = 0;
            for (int start = 0; start < d && start < mx; start++) {
                ArrayList<Long> nextmask = new ArrayList<>();
                long cmask = all;
                int cp = start;
                for (int i = 0; i < masks.size(); i++) {
                    if (i > 0 && cp == 0) {
                        nextmask.add(cmask);
                        cmask = all;
                    }
                    cmask &= rotateRight(masks.get(i), gen[cp]);
                    if (++cp == d) cp = 0;
                }
                nextmask.add(cmask);
                ans += count(nextmask, (mx - start + d - 1) / d);
            }
            return ans;
        }

    }

    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[1 << 16];
        private int curChar;
        private int numChars;

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

        public int[] readIntArray(int tokens) {
            int[] ret = new int[tokens];
            for (int i = 0; i < tokens; i++) {
                ret[i] = nextInt();
            }
            return ret;
        }

        public int read() {
            if (this.numChars == -1) {
                throw new InputMismatchException();
            } else {
                if (this.curChar >= this.numChars) {
                    this.curChar = 0;

                    try {
                        this.numChars = this.stream.read(this.buf);
                    } catch (IOException var2) {
                        throw new InputMismatchException();
                    }

                    if (this.numChars <= 0) {
                        return -1;
                    }
                }

                return this.buf[this.curChar++];
            }
        }

        public int nextInt() {
            int c;
            for (c = this.read(); isSpaceChar(c); c = this.read()) {
                ;
            }

            byte sgn = 1;
            if (c == 45) {
                sgn = -1;
                c = this.read();
            }

            int res = 0;

            while (c >= 48 && c <= 57) {
                res *= 10;
                res += c - 48;
                c = this.read();
                if (isSpaceChar(c)) {
                    return res * sgn;
                }
            }

            throw new InputMismatchException();
        }

        public long nextLong() {
            int c;
            for (c = this.read(); isSpaceChar(c); c = this.read()) {
                ;
            }

            byte sgn = 1;
            if (c == 45) {
                sgn = -1;
                c = this.read();
            }

            long res = 0L;

            while (c >= 48 && c <= 57) {
                res *= 10L;
                res += (long) (c - 48);
                c = this.read();
                if (isSpaceChar(c)) {
                    return res * (long) sgn;
                }
            }

            throw new InputMismatchException();
        }

        public static boolean isSpaceChar(int c) {
            return c == 32 || c == 10 || c == 13 || c == 9 || c == -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 println(long i) {
            writer.println(i);
        }

    }
}


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.util.InputMismatchException;
import java.math.BigInteger;
import java.io.IOException;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author tarek
 */
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);
        HMateuszAndAnInfiniteSequence solver = new HMateuszAndAnInfiniteSequence();
        solver.solve(1, in, out);
        out.close();
    }

    static class HMateuszAndAnInfiniteSequence {
        long[] lens;
        Description[] cache;
        int m;
        int[] b;
        int[] gen;

        public void solve(int testNumber, InputReader in, OutputWriter out) {
            int d = in.readInt();
            m = in.readInt();
            gen = new int[d];
            for (int i = 0; i < d; ++i) gen[i] = in.readInt();
            int blen = in.readInt();
            b = new int[blen];
            for (int i = 0; i < blen; ++i) {
                b[i] = in.readInt();
            }
            long left = in.readLong();
            long right = in.readLong();
            lens = new long[100];
            long len = 1;
            int layer = 0;
            lens[layer] = len;
            while (true) {
                ++layer;
                if (len < (right + d - 1) / d) {
                    len *= d;
                    lens[layer] = len;
                } else {
                    lens[layer] = right + 1;
                    break;
                }
            }
            cache = new Description[layer + 1];
            Description d1 = describe(layer, right);
            Description d2 = describe(layer, left + b.length - 2);
            long res = d1.matchesInside[0] - d2.matchesInside[0];
            out.printLine(res);
        }

        private Description describe(int layer, long upto) {
            if (upto > lens[layer]) throw new RuntimeException();
            if (upto == lens[layer]) {
                if (cache[layer] != null) return cache[layer];
            }
            Description res = null;
            if (upto <= 0) {
                res = new Description(upto);
                return res;
            }
            if (layer == 0) {
                res = new Description(upto);
                for (int shift = 0; shift < m; ++shift) {
                    if (b.length > 1 && b[0] >= shift) {
                        res.matchesPrefix[shift] = BigInteger.ONE;
                    } else {
                        res.matchesPrefix[shift] = BigInteger.ZERO;
                    }
                    if (b.length > 1 && b[b.length - 1] >= shift) {
                        res.matchesSuffix[shift] = BigInteger.ONE.shiftLeft(b.length - 1);
                    } else {
                        res.matchesSuffix[shift] = BigInteger.ZERO;
                    }
                    if (b.length == 1 && b[0] >= shift) {
                        ++res.matchesInside[shift];
                    }
                    byte[] bits = new byte[(b.length + 7) >> 3];
                    for (int i = 0; i < b.length; ++i) {
                        if (b[i] >= shift) {
                            bits[bits.length - 1 - (i >> 3)] |= (1 << (i & 7));
                        }
                    }
                    res.coveredIfStartsFrom[shift] = new BigInteger(1, bits);
                }
            } else {
                long togo = upto;
                for (int i = 0; i < gen.length && togo > 0; ++i) {
                    long by = Math.min(togo, lens[layer - 1]);
                    Description d = describe(layer - 1, by);
                    res = combine(res, d, gen[i]);
                    togo -= by;
                }
            }
            if (res == null) throw new RuntimeException();
            if (upto == lens[layer]) {
                cache[layer] = res;
            }
            return res;
        }

        private Description combine(Description a, Description b, int delta) {
            if (a == null) {
                if (delta != 0) throw new RuntimeException();
                return b;
            }
            Description res = new Description(a.len + b.len);
            for (int shift = 0; shift < m; ++shift) {
                int ashift = shift;
                int bshift = (shift + delta) % m;
                res.matchesInside[shift] = a.matchesInside[ashift] + b.matchesInside[bshift];
                res.matchesInside[shift] += a.matchesPrefix[ashift].and(b.matchesSuffix[bshift].shiftRight(1)).bitCount();
                res.matchesPrefix[shift] = b.matchesPrefix[bshift];
                if (b.len < this.b.length) {
                    res.matchesPrefix[shift] = res.matchesPrefix[shift].or(a.matchesPrefix[ashift].and(b.coveredIfStartsFrom[bshift].shiftRight(1)).shiftLeft((int) b.len));
                }
                res.matchesSuffix[shift] = a.matchesSuffix[ashift];
                if (a.len < this.b.length) {
                    res.matchesSuffix[shift] = res.matchesSuffix[shift].or(b.matchesSuffix[bshift].shiftRight((int) a.len).and(a.coveredIfStartsFrom[ashift]));
                }
                if (a.len < this.b.length) {
                    res.coveredIfStartsFrom[shift] = a.coveredIfStartsFrom[ashift].and(b.coveredIfStartsFrom[bshift].shiftRight((int) a.len));
                } else {
                    res.coveredIfStartsFrom[shift] = BigInteger.ZERO;
                }
            }
            return res;
        }

        class Description {
            long len;
            long[] matchesInside = new long[m];
            BigInteger[] matchesPrefix = new BigInteger[m];
            BigInteger[] matchesSuffix = new BigInteger[m];
            BigInteger[] coveredIfStartsFrom = new BigInteger[m];

            public Description(long len) {
                this.len = len;
            }

        }

    }

    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 printLine(long i) {
            writer.println(i);
        }

    }

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

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

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

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

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

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

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

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

        }

    }
}


/*
I am dead inside
Do you like NCT, sKz, BTS?
5 4 3 2 1 Moonwalk
Imma knock it down like domino
Is this what you want? Is this what you want?
Let's ttalkbocky about that
 */
import static java.lang.Math.*;
import java.util.*;
import java.io.*;
import java.math.*;

public class lolE
{
    static String target = "theseus";
    static int[] dx = {-1, 1, 0, 0, -1, -1, 1, 1};
    static int[] dy = {0, 0, -1, 1, -1, 1, -1, 1};
    public static void main(String omkar[]) throws Exception
    {
        BufferedReader infile = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(infile.readLine());
        int N = Integer.parseInt(st.nextToken());
        char[][] grid = new char[N][N];
        for(int r=0; r < N; r++)
            grid[r] = infile.readLine().trim().toCharArray();
        boolean[][] dp = new boolean[N][N];
        for(int r=0; r < N; r++)
            Arrays.fill(dp[r], true);
        for(int t=0; t < 7; t++)
        {
            boolean[][] next = new boolean[N][N];
            for(int r=0; r < N; r++)
                for(int c=0; c < N; c++)
                    if(grid[r][c] == target.charAt(t))
                    {
                        for(int d=0; d < 8; d++)
                        {
                            int x = r+dx[d];
                            int y = c+dy[d];
                            if(min(x,y) >= 0 && max(x,y) < N && dp[x][y])
                                next[r][c] = true;
                        }
                    }
            dp = next;
        }
        String res = "NO";
        for(int r=0; r < N; r++)
            for(int c=0; c < N; c++)
                if(dp[r][c])
                    res = "YES";
        System.out.println(res);
    }
}


import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int n = input.nextInt();
        String[] str = new String[n];
        for (int i = 0; i < n; i++) {
            str[i] = input.next();
        }
        if(n < 14)
            System.out.println("YES");
        else
            System.out.println("NO");
    }
}


/*
I am dead inside
Do you like NCT, sKz, BTS?
5 4 3 2 1 Moonwalk
Imma knock it down like domino
Is this what you want? Is this what you want?
Let's ttalkbocky about that
 */
import static java.lang.Math.*;
import java.util.*;
import java.io.*;
import java.math.*;

public class lolE
{
    static String target = "theseus";
    static String reverse = "sueseth";
    //static int[] dx = {-1, 1, 0, 0, -1, -1, 1, 1};
    //static int[] dy = {0, 0, -1, 1, -1, 1, -1, 1};
    //static int[] dx = {0, 1, 1};
    //static int[] dy = {1, 0, 1};
    public static void main(String omkar[]) throws Exception
    {
        BufferedReader infile = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(infile.readLine());
        int N = Integer.parseInt(st.nextToken());
        char[][] grid = new char[N][N];
        for(int r=0; r < N; r++)
            grid[r] = infile.readLine().trim().toCharArray();
        String res = "NO";
        for(int r=0; r < N; r++)
            for(int c=0; c < N-6; c++)
            {
                String temp = "";
                for(int i=c; i < c+7; i++)
                    temp += grid[r][i];
                if(temp.equals(target))
                    res = "YES";
            }
        for(int c=0; c < N; c++)
            for(int r=0; r < N-6; r++)
            {
                String temp = "";
                for(int i=r; i < r+7; i++)
                    temp += grid[i][c];
                if(temp.equals(target))
                    res = "YES";
            }
        //diagonals
        for(int r=0; r < N; r++)
            for(int c=0; c < N; c++)
            {
                String temp = "";
                int lol = 0;
                while(temp.length() < 7)
                {
                    if(max(r, c)+lol >= N)
                        break;
                    temp += grid[r+lol][c+lol];
                    lol++;
                }
                if(temp.equals(target))
                    res = "YES";
            }
        System.out.println(res);
    }
}


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

public class A {

    long mod = (long) 1e9 + 7;

    class Num {
        final long a, b;

        public Num(long a, long b) {
            this.a = a % mod;
            this.b = b % mod;
        }

        public Num add(Num other) {
            return new Num(a + other.a, b + other.b);
        }

        public Num multiply(Num other) {
            return new Num(a * other.a + 5 * b * other.b, a * other.b + b * other.a);
        }
    }

    int k;

    long[][] coeffs;

    void prepare() {
        coeffs = new long[k + 1][k + 1];
        long[][] tmpCoeffs = new long[k + 1][k + 1];
        long factK = 1;
        coeffs[0][0] = 1;

        for (int free = 0; free < k; free++) {
            factK = factK * (free + 1) % mod;

            for (int i = 0; i <= k; i++) {
                for (int j = 0; j <= k; j++) {
                    if (coeffs[i][j] != 0) {
                        tmpCoeffs[i + 1][j] += coeffs[i][j];
                        if (tmpCoeffs[i + 1][j] >= mod) {
                            tmpCoeffs[i + 1][j] -= mod;
                        }

                        tmpCoeffs[i][j + 1] += coeffs[i][j];
                        if (tmpCoeffs[i][j + 1] >= mod) {
                            tmpCoeffs[i][j + 1] -= mod;
                        }

                        long add = coeffs[i][j] * (mod - free) % mod;
                        tmpCoeffs[i][j] += add;
                        if (tmpCoeffs[i][j] >= mod) {
                            tmpCoeffs[i][j] -= mod;
                        }
                    }
                }
            }

            for (int i = 0; i <= k; i++) {
                for (int j = 0; j <= k; j++) {
                    coeffs[i][j] = tmpCoeffs[i][j];
                    tmpCoeffs[i][j] = 0;
                }
            }
        }

        factK = inv(factK);
        for (int i = 0; i <= k; i++) {
            for (int j = 0; j <= k; j++) {
                coeffs[i][j] = coeffs[i][j] * factK % mod;
            }
        }
        System.err.println(Arrays.deepToString(coeffs));

        pow1 = new Num[k + 1];
        powA = new Num[k + 1];
        pow2 = new Num[k + 1];
        powB = new Num[k + 1];

        pow1[0] = pow2[0] = powA[0] = powB[0] = new Num(1, 0);
        for (int i = 1; i <= k; i++) {
            pow1[i] = pow1[i - 1].multiply(PHI1);
            pow2[i] = pow2[i - 1].multiply(PHI2);
            powA[i] = powA[i - 1].multiply(A);
            powB[i] = powB[i - 1].multiply(B);
        }
    }

    long inv(long x) {
        return pow(x, mod - 2);
    }

    long pow(long a, long b) {
        long res = 1;
        while (b != 0) {
            if ((b & 1) == 1) {
                res = res * a % mod;
            }
            a = a * a % mod;
            b >>>= 1;
        }
        return res;
    }

    final Num PHI1 = new Num(inv(2), inv(2));
    final Num PHI2 = new Num(inv(2), mod - inv(2));
    final Num A = new Num(0, inv(5));
    final Num B = new Num(0, mod - inv(5));

    final Num ONE = new Num(1, 0);

    Num[] pow1, pow2, powA, powB;

    long get(long n) {
        Num result = new Num(0, 0);

        for (int i = 0; i <= k; i++) {
            for (int j = 0; j <= k; j++) {
                long coef = coeffs[i][j];
                if (coef == 0) {
                    continue;
                }

                Num cur = new Num(coef, 0).multiply(powA[i]).multiply(powB[j]);

                Num x = pow1[i].multiply(pow2[j]);
                x = geomSum(x, n + 1);

                result = result.add(cur.multiply(x));
            }
        }
        return result.a;
    }

    Num geomSum(Num x, long n) {
        if (n == 0) {
            return ONE;
        }
        if (n % 2 == 0) {
            Num x2 = x.multiply(x);
            Num result = geomSum(x2, n / 2);
            return (ONE.add(x)).multiply(result);
        } else {
            return ONE.add(x.multiply(geomSum(x, n - 1)));
        }
    }

    public void solve() {
        k = in.nextInt();
        prepare();
        long l = in.nextInt(), r = in.nextInt();
        for (int i = 1; i < 20; i++) {
            System.err.println(get(i) - get(i - 1));
        }
    }

    public void run() {
        in = new FastScanner();
        out = new PrintWriter(System.out);
        solve();
        out.close();
    }

    FastScanner in;
    PrintWriter out;

    class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        public FastScanner(String fileName) {
            try {
                br = new BufferedReader(new FileReader(fileName));
            } catch (FileNotFoundException e) {
            }
        }

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

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

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

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

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

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


import java.awt.*;
import java.io.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.List;

import static java.lang.Math.max;
import static java.lang.Math.min;

public class B implements Runnable{

    private final static Random rnd = new Random();

    // SOLUTION!!!
    // HACK ME PLEASE IF YOU CAN!!!
    // PLEASE!!!
    // PLEASE!!!
    // PLEASE!!!

    final int MAX_SIZE = 2000 * 1000;

    void solve() {
        int n = readInt();

        int c0 = readInt();
        int c1 = readInt();

        if (c0 > c1) {
            int tmp = c0;
            c0 = c1;
            c1 = tmp;
        }

        long answer = getAnswer(n, c0, c1);
        out.println(answer);
    }

    long getAnswer(int n, long c0, long c1) {
        long c01 = c0 + c1;

        if (n == 2) {
            return c01;
        }

        long answer = c1;
        n -= 2;

        long x = (c0 == 0 ? Integer.MAX_VALUE : c1 / c0);
        x = Math.min(x, n);

        answer += x * c1 + (x + 1) * (x + 2) / 2 * c0;
        n -= x;

        NavigableMap<Long, Integer> costs = new TreeMap<>();

//        costs.put(c1, 1);
        for (int count = 0; count <= Math.min(MAX_SIZE, x); ++count) {
            inc(costs, count * c0 + c1, 1);
        }
        inc(costs, (x + 1) * c0, 1);

        while (n > 0) {
            Map.Entry<Long, Integer> minCostEntry = costs.pollFirstEntry();

            long cost = minCostEntry.getKey();
            int count = minCostEntry.getValue();
            count = Math.min(count, n);

            n -= count;
            answer += (cost + c01) * count;

            inc(costs, cost + c0, count);
            inc(costs, cost + c1, count);
        }

        return answer;
    }

    void inc(NavigableMap<Long, Integer> counts, long cost, int count) {
        Integer curCount = counts.get(cost);
        if (curCount == null) {
            curCount = 0;
        }

        counts.put(cost, curCount + count);

        while (counts.size() > MAX_SIZE) {
            counts.pollLastEntry();
        }
    }

    /////////////////////////////////////////////////////////////////////

    private final static boolean FIRST_INPUT_STRING = false;
    private final static boolean MULTIPLE_TESTS = true;
    private final boolean ONLINE_JUDGE = System.getProperty("ONLINE_JUDGE") != null;

    private final static int MAX_STACK_SIZE = 128;

    private final static boolean OPTIMIZE_READ_NUMBERS = false;

    /////////////////////////////////////////////////////////////////////

    public void run(){
        try{
            timeInit();
            Locale.setDefault(Locale.US);

            init();

            if (ONLINE_JUDGE) {
                solve();
            } else {
                do {
                    try {
                        timeInit();
                        solve();
                        time();

                        out.println();
                    } catch (NumberFormatException e) {
                        break;
                    } catch (NullPointerException e) {
                        if (FIRST_INPUT_STRING) break;
                        else throw e;
                    }
                } while (MULTIPLE_TESTS);
            }

            out.close();
            time();
        }catch (Exception e){
            e.printStackTrace(System.err);
            System.exit(-1);
        }
    }

    /////////////////////////////////////////////////////////////////////

    private BufferedReader in;
    private OutputWriter out;
    private StringTokenizer tok = new StringTokenizer("");

    public static void main(String[] args){
        new Thread(null, new B(), "", MAX_STACK_SIZE * (1L << 20)).start();
    }

    /////////////////////////////////////////////////////////////////////

    private void init() throws FileNotFoundException{
        Locale.setDefault(Locale.US);

        if (ONLINE_JUDGE){
            in = new BufferedReader(new InputStreamReader(System.in));
            out = new OutputWriter(System.out);
        }else{
            in = new BufferedReader(new FileReader("input.txt"));
            out = new OutputWriter("output.txt");
        }
    }

    ////////////////////////////////////////////////////////////////

    private long timeBegin;

    private void timeInit() {
        this.timeBegin = System.currentTimeMillis();
    }

    private void time(){
        long timeEnd = System.currentTimeMillis();
        System.err.println("Time = " + (timeEnd - timeBegin));
    }

    private void debug(Object... objects){
        if (ONLINE_JUDGE){
            for (Object o: objects){
                System.err.println(o.toString());
            }
        }
    }

    /////////////////////////////////////////////////////////////////////

    private String delim = " ";

    private String readLine() {
        try {
            return in.readLine();
        } catch (IOException e) {
            throw new RuntimeIOException(e);
        }
    }

    private String readString() {
        try {
            while(!tok.hasMoreTokens()){
                tok = new StringTokenizer(readLine());
            }

            return tok.nextToken(delim);
        } catch (NullPointerException e) {
            return null;
        }
    }

    /////////////////////////////////////////////////////////////////

    private final char NOT_A_SYMBOL = '\0';

    private char readChar() {
        try {
            int intValue = in.read();

            if (intValue == -1){
                return NOT_A_SYMBOL;
            }

            return (char) intValue;
        } catch (IOException e) {
            throw new RuntimeIOException(e);
        }
    }

    private char[] readCharArray() {
        return readLine().toCharArray();
    }

    private char[][] readCharField(int rowsCount) {
        char[][] field = new char[rowsCount][];
        for (int row = 0; row < rowsCount; ++row) {
            field[row] = readCharArray();
        }

        return field;
    }

    /////////////////////////////////////////////////////////////////

    private long optimizedReadLong() {
        long result = 0;
        boolean started = false;
        while (true) {
            try {
                int j = in.read();
                if (-1 == j) {
                    if (started) return result;
                    throw new NumberFormatException();
                }

                if ('0' <= j && j <= '9') {
                    result = result * 10 + j - '0';
                    started = true;
                } else if (started) {
                    return result;
                }
            } catch (IOException e) {
                throw new RuntimeIOException(e);
            }
        }
    }

    private int readInt() {

        if (!OPTIMIZE_READ_NUMBERS) {
            return Integer.parseInt(readString());
        } else {
            return (int) optimizedReadLong();
        }
    }

    private int[] readIntArray(int size) {
        int[] array = new int[size];

        for (int index = 0; index < size; ++index){
            array[index] = readInt();
        }

        return array;
    }

    private int[] readSortedIntArray(int size) {
        Integer[] array = new Integer[size];

        for (int index = 0; index < size; ++index) {
            array[index] = readInt();
        }
        Arrays.sort(array);

        int[] sortedArray = new int[size];
        for (int index = 0; index < size; ++index) {
            sortedArray[index] = array[index];
        }

        return sortedArray;
    }

    private int[] readIntArrayWithDecrease(int size) {
        int[] array = readIntArray(size);

        for (int i = 0; i < size; ++i) {
            array[i]--;
        }

        return array;
    }

    ///////////////////////////////////////////////////////////////////

    private int[][] readIntMatrix(int rowsCount, int columnsCount) {
        int[][] matrix = new int[rowsCount][];

        for (int rowIndex = 0; rowIndex < rowsCount; ++rowIndex) {
            matrix[rowIndex] = readIntArray(columnsCount);
        }

        return matrix;
    }

    private int[][] readIntMatrixWithDecrease(int rowsCount, int columnsCount) {
        int[][] matrix = new int[rowsCount][];

        for (int rowIndex = 0; rowIndex < rowsCount; ++rowIndex) {
            matrix[rowIndex] = readIntArrayWithDecrease(columnsCount);
        }

        return matrix;
    }

    ///////////////////////////////////////////////////////////////////

    private long readLong() {
        if (!OPTIMIZE_READ_NUMBERS) {
            return Long.parseLong(readString());
        } else {
            return optimizedReadLong();
        }
    }

    private long[] readLongArray(int size) {
        long[] array = new long[size];

        for (int index = 0; index < size; ++index){
            array[index] = readLong();
        }

        return array;
    }

    ////////////////////////////////////////////////////////////////////

    private double readDouble() {
        return Double.parseDouble(readString());
    }

    private double[] readDoubleArray(int size) {
        double[] array = new double[size];

        for (int index = 0; index < size; ++index){
            array[index] = readDouble();
        }

        return array;
    }

    ////////////////////////////////////////////////////////////////////

    private BigInteger readBigInteger() {
        return new BigInteger(readString());
    }

    private BigDecimal readBigDecimal() {
        return new BigDecimal(readString());
    }

    /////////////////////////////////////////////////////////////////////

    private Point readPoint() {
        int x = readInt();
        int y = readInt();
        return new Point(x, y);
    }

    private Point[] readPointArray(int size) {
        Point[] array = new Point[size];

        for (int index = 0; index < size; ++index){
            array[index] = readPoint();
        }

        return array;
    }

    /////////////////////////////////////////////////////////////////////

    private List<Integer>[] readGraph(int vertexNumber, int edgeNumber) {
        @SuppressWarnings("unchecked")
        List<Integer>[] graph = new List[vertexNumber];

        for (int index = 0; index < vertexNumber; ++index){
            graph[index] = new ArrayList<Integer>();
        }

        while (edgeNumber-- > 0){
            int from = readInt() - 1;
            int to = readInt() - 1;

            graph[from].add(to);
            graph[to].add(from);
        }

        return graph;
    }

    /////////////////////////////////////////////////////////////////////

    private static class IntIndexPair {

        static Comparator<IntIndexPair> increaseComparator = new Comparator<B.IntIndexPair>() {

            @Override
            public int compare(B.IntIndexPair indexPair1, B.IntIndexPair indexPair2) {
                int value1 = indexPair1.value;
                int value2 = indexPair2.value;

                if (value1 != value2) return value1 - value2;

                int index1 = indexPair1.index;
                int index2 = indexPair2.index;

                return index1 - index2;
            }
        };

        static Comparator<IntIndexPair> decreaseComparator = new Comparator<B.IntIndexPair>() {

            @Override
            public int compare(B.IntIndexPair indexPair1, B.IntIndexPair indexPair2) {
                int value1 = indexPair1.value;
                int value2 = indexPair2.value;

                if (value1 != value2) return -(value1 - value2);

                int index1 = indexPair1.index;
                int index2 = indexPair2.index;

                return index1 - index2;
            }
        };

        int value, index;

        IntIndexPair(int value, int index) {
            super();
            this.value = value;
            this.index = index;
        }

        int getRealIndex() {
            return index + 1;
        }
    }

    private IntIndexPair[] readIntIndexArray(int size) {
        IntIndexPair[] array = new IntIndexPair[size];

        for (int index = 0; index < size; ++index) {
            array[index] = new IntIndexPair(readInt(), index);
        }

        return array;
    }

    /////////////////////////////////////////////////////////////////////

    private static class OutputWriter extends PrintWriter {

        final int DEFAULT_PRECISION = 12;

        private int precision;
        private String format, formatWithSpace;

        {
            precision = DEFAULT_PRECISION;

            format = createFormat(precision);
            formatWithSpace = format + " ";
        }

        OutputWriter(OutputStream out) {
            super(out);
        }

        OutputWriter(String fileName) throws FileNotFoundException {
            super(fileName);
        }

        int getPrecision() {
            return precision;
        }

        void setPrecision(int precision) {
            precision = max(0, precision);
            this.precision = precision;

            format = createFormat(precision);
            formatWithSpace = format + " ";
        }

        String createFormat(int precision){
            return "%." + precision + "f";
        }

        @Override
        public void print(double d){
            printf(format, d);
        }

        void printWithSpace(double d){
            printf(formatWithSpace, d);
        }

        void printAll(double...d){
            for (int i = 0; i < d.length - 1; ++i){
                printWithSpace(d[i]);
            }

            print(d[d.length - 1]);
        }

        @Override
        public void println(double d){
            printlnAll(d);
        }

        void printlnAll(double... d){
            printAll(d);
            println();
        }
    }

    /////////////////////////////////////////////////////////////////////

    private static class RuntimeIOException extends RuntimeException {

        /**
         *
         */
        private static final long serialVersionUID = -6463830523020118289L;

        RuntimeIOException(Throwable cause) {
            super(cause);
        }
    }

    /////////////////////////////////////////////////////////////////////
    //////////////// Some useful constants and functions ////////////////
    /////////////////////////////////////////////////////////////////////

    private static final int[][] steps = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
    private static final int[][] steps8 = {
            {-1, 0}, {1, 0}, {0, -1}, {0, 1},
            {-1, -1}, {1, 1}, {1, -1}, {-1, 1}
    };

    private static boolean checkCell(int row, int rowsCount, int column, int columnsCount) {
        return checkIndex(row, rowsCount) && checkIndex(column, columnsCount);
    }

    private static boolean checkIndex(int index, int lim){
        return (0 <= index && index < lim);
    }

    /////////////////////////////////////////////////////////////////////

    private static boolean checkBit(int mask, int bit){
        return (mask & (1 << bit)) != 0;
    }
    private static boolean checkBit(long mask, int bit){
        return (mask & (1L << bit)) != 0;
    }

    /////////////////////////////////////////////////////////////////////

    private static long getSum(int[] array) {
        long sum = 0;
        for (int value: array) {
            sum += value;
        }

        return sum;
    }

    private static Point getMinMax(int[] array) {
        int min = array[0];
        int max = array[0];

        for (int index = 0, size = array.length; index < size; ++index, ++index) {
            int value = array[index];

            if (index == size - 1) {
                min = min(min, value);
                max = max(max, value);
            } else {
                int otherValue = array[index + 1];

                if (value <= otherValue) {
                    min = min(min, value);
                    max = max(max, otherValue);
                } else {
                    min = min(min, otherValue);
                    max = max(max, value);
                }
            }
        }

        return new Point(min, max);
    }

    /////////////////////////////////////////////////////////////////////

    private static int[] getPrimes(int n) {
        boolean[] used = new boolean[n];
        used[0] = used[1] = true;

        int size = 0;
        for (int i = 2; i < n; ++i) {
            if (!used[i]) {
                ++size;
                for (int j = 2 * i; j < n; j += i) {
                    used[j] = true;
                }
            }
        }

        int[] primes = new int[size];
        for (int i = 0, cur = 0; i < n; ++i) {
            if (!used[i]) {
                primes[cur++] = i;
            }
        }

        return primes;
    }

    /////////////////////////////////////////////////////////////////////

    private static long lcm(long a, long b) {
        return a / gcd(a, b) * b;
    }

    private static long gcd(long a, long b) {
        return (a == 0 ? b : gcd(b % a, a));
    }

    /////////////////////////////////////////////////////////////////////

    private static class IdMap<KeyType> extends HashMap<KeyType, Integer> {

        /**
         *
         */
        private static final long serialVersionUID = -3793737771950984481L;

        public IdMap() {
            super();
        }

        int getId(KeyType key) {
            Integer id = super.get(key);
            if (id == null) {
                super.put(key, id = size());
            }

            return id;
        }
    }
}


//package bubblecup9f;
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 B2 {
	InputStream is;
	PrintWriter out;
	String INPUT = "";

	void solve()
	{
		int n = ni(), c0 = ni(), c1 = ni();
		if(c0 > c1){
			int d = c0;c0 = c1; c1 = d;
		}
		if(c0 == 0){
			out.println((long)c1*(n-1));
			return;
		}

		long low = -1, high = 100000000000000000L;
		while(high - low > 1){
			long h = high+low>>1; // sup of split node's cost
			long eled = 0;
			for(long nc1 = 0;h-nc1*c1 >= 0;nc1++){
				long nc0 = (h-nc1*c1)/c0;
				// C(nc1+0,nc1)+C(nc1+1,nc1)+...+(nc1+nc0,nc0) # eliminated nodes
				// C(nc1+nc0+1,nc0+1)
				eled += roughC(nc1+nc0+1,nc1+1,18);
				if(eled > n-1)break;
			}
			if(eled >= n-1){
				high = h;
			}else{
				low = h;
			}
		}
		tr(high);

		{
			long ret = (long)(c0+c1)*(n-1); // # branch
			long eled = 0;
			for(long nc1 = 0;low-nc1*c1 >= 0;nc1++){
				long nc0 = (low-nc1*c1)/c0;
				// C(nc1+0,nc1)+C(nc1+1,nc1)+...+(nc1+nc0,nc1) # eliminated nodes
				// C(nc1+nc0+1,nc1+1)
				long val = roughC(nc1+nc0+1,nc1+1,18);
				eled += val;
				// none 0
				// C(nc1+0,nc1)*nc1*c1+C(nc1+1,nc1)*(c0+nc1*c1)+...+(nc1+nc0,nc1)*(nc0*c0+nc1*c1) # eliminated nodes
				// C(nc1+nc0+1,nc1+1)-C(nc1+k,nc1+1)
				// nc0*C(nc1+nc0+1,nc1+1)-C(nc1+nc0+1,nc1+1+1)
				// c1*val*nc1 + c0*(val*(nc0+1)-val)
				ret += c1*nc1*val + c0*(nc0*val-roughC(nc1+nc0+1,nc1+2,18));
			}
			long rem = n-1-eled;
			ret += rem * (low+1);
			out.println(ret);
		}
	}

	public static long roughC(long n, long r, double lim)
	{
		if(n < r || r < 0 || n < 0)return 0;
		if(r > n/2)r = n - r;
		if(r == 0)return 1;
		double logc = (n+0.5)*Math.log10(n)+(-r-0.5)*Math.log10(r)+(-n+r-0.5)*Math.log10(n-r)-Math.log10(2*Math.PI)/2;
		if(logc >= lim)return Long.MAX_VALUE/2;
		long x = 1;
		for(int i = 0;i < r;i++) {
			x *= n-i;
			x /= i+1;
		}
		return x;
	}

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

	private byte[] inbuf = new byte[1024];
	private 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.*;
import java.util.*;

public class B {

    long n, c0, c1;

    public void solve() {
        n = in.nextInt() - 1;
        c0 = in.nextInt();
        c1 = in.nextInt();
        if (c0 > c1) {
            long tmp = c0;
            c0 = c1;
            c1 = tmp;
        }

        if (c0 == 0) {
            out.println(1L * n * (c0 + c1));
            return;
        }

        long left = 0, right = (long) 5e17;

        while (left < right - 1) {
            long mid = (left + right) >>> 1;

            long[] calc = calc(mid);
            if (calc[0] < n) {
                left = mid;
            } else {
                right = mid;
            }
        }
        System.err.println(left);
        long[] calc2 = calc(left);

        long result = calc2[1] + (n - calc2[0]) * (left + 1);
        result += 1L * n * (c0 + c1);
        out.println(result);
    }

    long[] calc(long x) {
        long count = 0, sum = 0;
        for (long j = 0; c1 * j <= x; j++) {
            long maxI = (x - c1 * j) / c0;
            if (j == 0) {
                count += (maxI + 1);
                sum += c0 * maxI * (maxI + 1) / 2;
            } else {
                long curChoose = 1;
                for (long i = 0; i * c0 + j * c1 <= x; i++) {
                    if (i > 0) {
                        curChoose *= (i + j);
                        curChoose /= i;
                    }
                    count += curChoose;
                    sum += curChoose * (i * c0 + j * c1);
                    if (count >= n) {
                        return new long[]{count, sum};
                    }
                }
            }
        }
        return new long[]{count, sum};
    }

    public void run() {
        in = new FastScanner();
        out = new PrintWriter(System.out);
        solve();
        out.close();
    }

    FastScanner in;
    PrintWriter out;

    class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        public FastScanner(String fileName) {
            try {
                br = new BufferedReader(new FileReader(fileName));
            } catch (FileNotFoundException e) {
            }
        }

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

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

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

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

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

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


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.io.Closeable;
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) throws Exception {
        Thread thread = new Thread(null, new TaskAdapter(), "", 1 << 27);
        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);
            FastOutput out = new FastOutput(outputStream);
            GBeautifulMatrix solver = new GBeautifulMatrix();
            solver.solve(1, in, out);
            out.close();
        }
    }

    static class GBeautifulMatrix {
        Modular mod = new Modular(998244353);
        Factorial factorial = new Factorial(2000, mod);

        public void solve(int testNumber, FastInput in, FastOutput out) {
            int n = in.readInt();
            int[][] mat = new int[n][n];
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) {
                    mat[i][j] = in.readInt();
                }
            }

            PermutationWithDistinctForbiddenMatch permutation = new PermutationWithDistinctForbiddenMatch(mod, n);
            int[] follow = new int[n + 1];
            follow[0] = 1;
            for (int i = 1; i <= n; i++) {
                follow[i] = mod.mul(follow[i - 1], permutation.get(n, 0));
            }

            int ans = 0;

            int[] indexOfVal = new int[n + 1];
            int[] indexOfDim = new int[n + 1];
            IntegerBIT deleteBit = new IntegerBIT(n);
            IntegerBIT floatBIT = new IntegerBIT(n);
            IntegerBIT solidBIT = new IntegerBIT(n);

            int[][] floatSummary = new int[n][n];
            int[][] solidSummary = new int[n][n];
            int[][] floatCnt = new int[n][n];
            int[] solid = new int[n + 1];
            final int NONE = 0;
            final int SOLID = 1;
            final int FLOAT = 2;
            for (int i = 1; i < n; i++) {
                solidBIT.clear();
                floatBIT.clear();
                for (int j = 1; j <= n; j++) {
                    solidBIT.update(j, 1);
                    solid[j] = SOLID;
                }
                for (int j = 0; j < n; j++) {
                    floatCnt[i][j] = floatBIT.query(n);
                    floatSummary[i][j] = floatBIT.query(mat[i][j] - 1);
                    solidSummary[i][j] = solidBIT.query(mat[i][j] - 1);
                    if (solid[mat[i - 1][j]] == SOLID && mat[i - 1][j] < mat[i][j]) {
                        solidSummary[i][j] -= 1;
                    }
                    if (solid[mat[i - 1][j]] == FLOAT && mat[i - 1][j] < mat[i][j]) {
                        floatSummary[i][j] -= 1;
                    }
                    if (solid[mat[i - 1][j]] == SOLID) {
                        solidBIT.update(mat[i - 1][j], -1);
                        floatBIT.update(mat[i - 1][j], 1);
                        solid[mat[i - 1][j]] = FLOAT;
                    }

                    if (solid[mat[i][j]] == SOLID) {
                        solidBIT.update(mat[i][j], -1);
                    } else {
                        floatBIT.update(mat[i][j], -1);
                    }
                    solid[mat[i][j]] = NONE;
                }
            }

            deleteBit.clear();
            for (int j = 0; j < n; j++) {
                int cnt = mat[0][j] - 1 - deleteBit.query(mat[0][j] - 1);
                int contrib = mod.mul(cnt, factorial.fact(n - j - 1));
                contrib = mod.mul(contrib, follow[n - 1]);
                ans = mod.plus(ans, contrib);
                deleteBit.update(mat[0][j], 1);
            }

            for (int i = 1; i < n; i++) {
                for (int j = 0; j < n; j++) {
                    indexOfVal[mat[i][j]] = j;
                    indexOfDim[mat[i - 1][j]] = j;
                }
                for (int j = 0; j < n - 1; j++) {
                    //float
                    int cnt = floatSummary[i][j];
                    int floatRemain = floatCnt[i][j] - 1;
                    if (floatRemain < 0) {
                        continue;
                    }
                    if (indexOfVal[mat[i - 1][j]] > j) {
                        floatRemain++;
                    }
                    int remain = n - j - 1;
                    int contrib = mod.mul(cnt, permutation.get(remain - floatRemain, floatRemain));
                    contrib = mod.mul(contrib, follow[n - i - 1]);
                    ans = mod.plus(ans, contrib);
                }
                for (int j = 0; j < n - 1; j++) {
                    //solid
                    int cnt = solidSummary[i][j];
                    if (cnt == 0) {
                        continue;
                    }
                    int floatRemain = floatCnt[i][j] + 1;
                    if (indexOfVal[mat[i - 1][j]] < j) {
                        floatRemain--;
                    }
                    int remain = n - j - 1;
                    int contrib = mod.mul(cnt, permutation.get(remain - floatRemain, floatRemain));
                    contrib = mod.mul(contrib, follow[n - i - 1]);
                    ans = mod.plus(ans, contrib);
                }
            }

            out.println(ans);
        }

    }

    static class PermutationWithDistinctForbiddenMatch {
        private int[][] dp;
        private int[][] dp2;

        public PermutationWithDistinctForbiddenMatch(Modular mod, int n) {
            this.dp = new int[n + 1][n + 1];
            dp[0][0] = 1;
            for (int i = 1; i <= n; i++) {
                for (int j = 0; j <= i; j++) {
                    dp[i][j] = mod.mul(dp[i - 1][j], j + j);
                    if (j + 1 <= n) {
                        dp[i][j] = mod.plus(dp[i][j], dp[i - 1][j + 1]);
                    }
                    if (j > 0) {
                        dp[i][j] = mod.plus(dp[i][j], mod.mul(dp[i - 1][j - 1], mod.mul(j, j)));
                    }
                }
            }

            dp2 = new int[n + 1][n + 1];
            for (int i = 0; i <= n; i++) {
                for (int j = 0; j <= n; j++) {
                    if (j == 0) {
                        dp2[i][j] = dp[i][j];
                        continue;
                    }
                    if (j > 0) {
                        dp2[i][j] = mod.plus(dp2[i][j], mod.mul(dp2[i][j - 1], j));
                    }
                    if (i > 0) {
                        dp2[i][j] = mod.plus(dp2[i][j], mod.mul(dp2[i - 1][j], i));
                    }
                }
            }

//        System.err.println(Arrays.deepToString(dp));
//        System.err.println(Arrays.deepToString(dp2));
        }

        public int get(int i, int j) {
            return dp2[i][j];
        }

    }

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

    }

    static class Modular {
        int m;

        public int getMod() {
            return m;
        }

        public Modular(int m) {
            this.m = m;
        }

        public Modular(long m) {
            this.m = (int) m;
            if (this.m != m) {
                throw new IllegalArgumentException();
            }
        }

        public Modular(double m) {
            this.m = (int) m;
            if (this.m != m) {
                throw new IllegalArgumentException();
            }
        }

        public int valueOf(int x) {
            x %= m;
            if (x < 0) {
                x += m;
            }
            return x;
        }

        public int valueOf(long x) {
            x %= m;
            if (x < 0) {
                x += m;
            }
            return (int) x;
        }

        public int mul(int x, int y) {
            return valueOf((long) x * y);
        }

        public int plus(int x, int y) {
            return valueOf(x + y);
        }

        public String toString() {
            return "mod " + m;
        }

    }

    static class IntegerBIT {
        private int[] data;
        private int n;

        public IntegerBIT(int n) {
            this.n = n;
            data = new int[n + 1];
        }

        public int query(int i) {
            int sum = 0;
            for (; i > 0; i -= i & -i) {
                sum += data[i];
            }
            return sum;
        }

        public void update(int i, int mod) {
            if (i <= 0) {
                return;
            }
            for (; i <= n; i += i & -i) {
                data[i] += mod;
            }
        }

        public void clear() {
            Arrays.fill(data, 0);
        }

        public String toString() {
            StringBuilder builder = new StringBuilder();
            for (int i = 1; i <= n; i++) {
                builder.append(query(i) - query(i - 1)).append(' ');
            }
            return builder.toString();
        }

    }

    static class FastOutput implements AutoCloseable, Closeable {
        private StringBuilder cache = new StringBuilder(10 << 20);
        private final Writer os;

        public FastOutput(Writer os) {
            this.os = os;
        }

        public FastOutput(OutputStream os) {
            this(new OutputStreamWriter(os));
        }

        public FastOutput println(int c) {
            cache.append(c).append('\n');
            return this;
        }

        public FastOutput flush() {
            try {
                os.append(cache);
                os.flush();
                cache.setLength(0);
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
            return this;
        }

        public void close() {
            flush();
            try {
                os.close();
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        }

        public String toString() {
            return cache.toString();
        }

    }

    static class InverseNumber {
        int[] inv;

        public InverseNumber(int[] inv, int limit, Modular modular) {
            this.inv = inv;
            inv[1] = 1;
            int p = modular.getMod();
            for (int i = 2; i <= limit; i++) {
                int k = p / i;
                int r = p % i;
                inv[i] = modular.mul(-k, inv[r]);
            }
        }

        public InverseNumber(int limit, Modular modular) {
            this(new int[limit + 1], limit, modular);
        }

    }

    static class Factorial {
        int[] fact;
        int[] inv;
        Modular modular;

        public Factorial(int[] fact, int[] inv, InverseNumber in, int limit, Modular modular) {
            this.modular = modular;
            this.fact = fact;
            this.inv = inv;
            fact[0] = inv[0] = 1;
            for (int i = 1; i <= limit; i++) {
                fact[i] = modular.mul(fact[i - 1], i);
                inv[i] = modular.mul(inv[i - 1], in.inv[i]);
            }
        }

        public Factorial(int limit, Modular modular) {
            this(new int[limit + 1], new int[limit + 1], new InverseNumber(limit, modular), limit, modular);
        }

        public int fact(int n) {
            return fact[n];
        }

    }
}