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 leftBIT = new IntegerBIT(n);
            IntegerBIT rightBIT = new IntegerBIT(n);

            int[][] live = new int[n][n];
            int[][] left = new int[n][n];
            int[][] right = new int[n][n];
            MultiWayIntegerStack s1 = new MultiWayIntegerStack(n, n);
            MultiWayIntegerStack s2 = new MultiWayIntegerStack(n, n);
            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;
                }

                leftBIT.clear();
                rightBIT.clear();
                s1.clear();
                s2.clear();
                for (int j = n - 1; j >= 0; j--) {
                    right[i][j] = rightBIT.query(mat[i][j] - 1);
                    if (mat[i - 1][j] < mat[i][j]) {
                        right[i][j] -= rightBIT.query(mat[i - 1][j]) - rightBIT.query(mat[i - 1][j] - 1);
                    }
                    left[i][j] = leftBIT.query(mat[i][j] - 1);
                    if (mat[i - 1][j] < mat[i][j]) {
                        left[i][j] -= leftBIT.query(mat[i - 1][j]) - leftBIT.query(mat[i - 1][j] - 1);
                    }
                    live[i][j] = rightBIT.query(n);

                    if (indexOfVal[mat[i - 1][j]] <= j) {
                        s1.addLast(indexOfVal[mat[i - 1][j]], j);
                    } else {
                        rightBIT.update(mat[i - 1][j], 1);
                    }

                    if (indexOfDim[mat[i][j]] <= j) {
                        s2.addLast(indexOfDim[mat[i][j]], j);
                        leftBIT.update(mat[i][j], 1);
                    } else {
                    }

                    while (!s1.isEmpty(j)) {
                        int tail = s1.removeLast(j);
                        //leftBIT.update(mat[i - 1][tail], -1);
                        rightBIT.update(mat[i - 1][tail], 1);
                    }

                    while (!s2.isEmpty(j)) {
                        int tail = s2.removeLast(j);
                        leftBIT.update(mat[i][tail], -1);
                    }
                }

            }

            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; j++) {
                    //from left
                    if (left[i][j] == 0) {
                        continue;
                    }
                    int contrib = left[i][j];
                    int remain = n - 1 - j;
                    int l = live[i][j];
                    if (indexOfDim[mat[i][j]] > j) {
                        l++;
                    }
                    contrib = mod.mul(contrib, permutation.get(l, remain - l));
                    contrib = mod.mul(contrib, follow[n - 1 - i]);
                    ans = mod.plus(ans, contrib);
                }
                for (int j = 0; j < n; j++) {
                    //from right
                    if (right[i][j] == 0) {
                        continue;
                    }
                    int contrib = right[i][j];
                    int remain = n - 1 - j;
                    int l = live[i][j];
                    if (indexOfDim[mat[i][j]] > j) {
                        l++;
                    }
                    contrib = mod.mul(contrib, permutation.get(l - 1, remain - (l - 1)));
                    contrib = mod.mul(contrib, follow[n - 1 - i]);
                    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 interface IntegerIterator {
        boolean hasNext();

        int next();

    }

    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 MultiWayIntegerStack {
        private int[] values;
        private int[] next;
        private int[] heads;
        private int alloc;
        private int stackNum;

        public IntegerIterator iterator(final int queue) {
            return new IntegerIterator() {
                int ele = heads[queue];

                public boolean hasNext() {
                    return ele != 0;
                }

                public int next() {
                    int ans = values[ele];
                    ele = next[ele];
                    return ans;
                }
            };
        }

        private void doubleCapacity() {
            int newSize = Math.max(next.length + 10, next.length * 2);
            next = Arrays.copyOf(next, newSize);
            values = Arrays.copyOf(values, newSize);
        }

        public void alloc() {
            alloc++;
            if (alloc >= next.length) {
                doubleCapacity();
            }
            next[alloc] = 0;
        }

        public void clear() {
            alloc = 0;
            Arrays.fill(heads, 0, stackNum, 0);
        }

        public boolean isEmpty(int qId) {
            return heads[qId] == 0;
        }

        public MultiWayIntegerStack(int qNum, int totalCapacity) {
            values = new int[totalCapacity + 1];
            next = new int[totalCapacity + 1];
            heads = new int[qNum];
            stackNum = qNum;
        }

        public void addLast(int qId, int x) {
            alloc();
            values[alloc] = x;
            next[alloc] = heads[qId];
            heads[qId] = alloc;
        }

        public int removeLast(int qId) {
            int ans = values[heads[qId]];
            heads[qId] = next[heads[qId]];
            return ans;
        }

        public String toString() {
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < stackNum; i++) {
                builder.append(i).append(": ");
                for (IntegerIterator iterator = iterator(i); iterator.hasNext(); ) {
                    builder.append(iterator.next()).append(",");
                }
                if (builder.charAt(builder.length() - 1) == ',') {
                    builder.setLength(builder.length() - 1);
                }
                builder.append('\n');
            }
            return builder.toString();
        }

    }

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

    }
}


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

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

    static class EBeautifulMatrix {
        long[] fac;
        int mod = 998244353;
        long[][] dp;

        public void solve(int testNumber, InputReader in, OutputWriter out) {
            int n = in.nextInt();

            int[][] a = new int[n][n];

            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) {
                    a[i][j] = in.nextInt() - 1;
                }
            }

            fac = new long[2001];

            fac[0] = 1;

            for (int i = 1; i <= 2000; i++) {
                fac[i] = (i * fac[i - 1]) % mod;
            }

            long[] rank = new long[n];

            rank[0] = calRank(a[0], n);

            long tot = calTot(n);
            for (int i = 1; i < n; i++) {
                rank[i] = calDel(a[i - 1], a[i], n);
            }

            long ans = rank[0];

            for (int i = 1; i < n; i++) {
                ans *= tot;
                ans %= mod;

                ans += rank[i];
                ans %= mod;
            }

            out.println(ans);
        }

        long calRank(int[] a, int n) {
            long rank = 0;

            BinaryIndexedTree bit = new BinaryIndexedTree(n);
            for (int i = 0; i < n; i++) {
                int num = a[i];

                int prev = 0;
                if (num > 0) {
                    prev = num - bit.sum(num - 1);
                }

                if (prev > 0) {
                    rank += prev * fac[n - 1 - i];
                    rank %= mod;
                }

                bit.update(num, 1);
            }

            return rank;
        }

        long calTot(int n) {

            dp = new long[n + 1][n + 1];

            dp[0][0] = 1;
            dp[1][0] = 1;

            for (int i = 2; i <= n; i++) {
                for (int j = 0; j <= i; j++) {
                    if (i > j) {
                        if (j > 0) {
                            dp[i][j] += j * dp[i - 1][j - 1];
                            dp[i][j] %= mod;
                        }
                        dp[i][j] += (i - j) * dp[i - 1][j];
                        dp[i][j] %= mod;
                    } else {
                        dp[i][j] += (i - 1) * dp[i - 1][j - 2];
                        dp[i][j] %= mod;
                    }
                }
            }

            return dp[n][n];
        }

        long calDel(int[] pa, int[] a, int n) {

            long rank = 0;

            BinaryIndexedTree sbit = new BinaryIndexedTree(n);
            BinaryIndexedTree nsbit = new BinaryIndexedTree(n);

            for (int i = 0; i < n; i++) {
                sbit.update(i, 1);
            }

            int totsame = n;

            for (int i = 0; i < n; i++) {
                int same = sbit.sum(a[i] - 1);
                int usame = nsbit.sum(a[i] - 1);

                if (pa[i] < a[i]) {
                    int val = sbit.value(pa[i]);

                    same -= val;
                }

                if (sbit.value(pa[i]) == 1) {
                    if (totsame > 1)
                        rank += same * dp[n - 1 - i][totsame - 2];
                    rank %= mod;
                    if (totsame > 0)
                        rank += usame * dp[n - 1 - i][totsame - 1];

                    sbit.update(pa[i], -1);
                    nsbit.update(pa[i], 1);

                    totsame--;
                } else {
                    if (totsame > 0)
                        rank += same * dp[n - 1 - i][totsame - 1];
                    rank %= mod;
                    rank += usame * dp[n - 1 - i][totsame];
                }

                if (sbit.value(a[i]) == 1) {
                    sbit.update(a[i], -1);
                    totsame--;
                } else {
                    nsbit.update(a[i], -1);
                }

                rank %= mod;
            }

            return rank;
        }

        class BinaryIndexedTree {
            int n;
            int[] tree;

            public BinaryIndexedTree(int n) {
                super();
                this.n = n;
                this.tree = new int[n + 1];
            }

            public int sum(int idx) {
                idx++;

                int sum = 0;

                while (idx > 0) {
                    sum += tree[idx];
                    idx -= (idx & -idx);
                }

                return sum;
            }

            public void update(int idx, int v) {
                idx++;

                while (idx <= n) {
                    tree[idx] += v;
                    idx += (idx & -idx);
                }
            }

            public int value(int i) {
                int val = sum(i);

                if (i > 0) {
                    val -= sum(i - 1);
                }

                return val;
            }

        }

    }

    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 static boolean isWhitespace(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

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

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

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

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

        }

    }

    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.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.StringTokenizer;

public class E {
	static PrintWriter out = new PrintWriter(System.out);

	static int MAX = 2005;
	static long mod = 998_244_353L;
	static long fact[];
	static long dp[][];

	static int N;
	static int mat[][];
	public static void main(String[] args) {
		FS in = new FS();
		fact = new long[MAX];
		fact[0] = 1;
		for(int i = 1; i < MAX; i++) fact[i] = (fact[i-1]*i)%mod;
		dp = new long[MAX][MAX];
		for(long a[] : dp) Arrays.fill(a, -1);

		N = in.nextInt();
		mat = new int[N][N];
		for(int i = 0; i < N; i++)
			for(int j = 0; j < N; j++)
				mat[i][j] = in.nextInt()-1;

		long whenFree = go(N, N);
		long freePow[] = new long[N+1];
		freePow[0] = 1;
		for(int i = 1; i <= N; i++) {
			freePow[i] = (whenFree * freePow[i-1])%mod;
		}

//		for(int i = 1; i <= N; i++) {
//			for(int j = 0; j <= i; j++) {
//				System.out.println("n="+i+" ab="+j+" res = "+go(i,j));
//			}
//		}

		long res = 0;
		for(int i = 0; i < N; i++) {
			int sz = N;
			BIT have = new BIT(N);
			for(int j = 0; j < N; j++) have.update(j, 1);

			for(int j = 0; j < N; j++) {
				sz--;
				// place something less than it
				long areLess = have.sum(0, mat[i][j]-1);
				if(i > 0 && mat[i-1][j] < mat[i][j]) areLess -= have.sum(mat[i-1][j], mat[i-1][j]);
				res = add(res, mult(freePow[N-i-1], mult(areLess, go(sz, (i == 0 ? 0 : sz)))));

//				System.out.println(i+" "+j+"  less = "+areLess+" above = "+sz+"  res = "+res);

				// place the current element and continue
				have.update(mat[i][j], -1);
			}
		}
		out.println(res);
		out.close();
	}

	static long go(int n, int above) {
		if(n <= 0 || above < 0) return 0;
		if(n == 1) return above == 1 ? 0 : 1;
		if(above == 0) return fact[n];
		if(dp[n][above] != -1) return dp[n][above];
		long free = n-above;
		long notFree = above-1;
		long res = 0;
		res += (free * go(n-1, above-1));
		res += (notFree * go(n-1, above-2));
		return dp[n][above] = res%mod;
	}

	static long add(long a, long b) {
		long x = a+b;
		return x >= mod ? x-mod : x;
	}
	static long mult(long a, long b) {
		long x = a*b;
		return x >= mod ? x%mod : x;
	}

	static class BIT {
		int n;
		int[] tree;

		public BIT(int n) {
			this.n = n;
			tree = new int[n + 2];
		}

		int read(int i) {
			i++;
			int sum = 0;
			while (i > 0) {
				sum += tree[i];
				i -= i & -i;
			}
			return sum;
		}

		int sum(int a, int b) {
			if(a > b) return 0;
			return read(b) - (a == 0 ? 0 : read(a-1));
		}

		void update(int i, int val) {
			i++;
			while (i <= n) {
				tree[i] += val;
				i += i & -i;
			}
		}

		// if the BIT is a freq array, returns the
		// index of the kth item, or n if there are fewer
		// than k items.
		int getKth(int k) {
			int e=Integer.highestOneBit(n), o=0;
			for (; e!=0; e>>=1) {
				if (e+o<=n && tree[e+o]<=k) {
					k-=tree[e+o];
					o+=e;
				}
			}
			return o;
		}

	}

	static class FS{
		BufferedReader br;
		StringTokenizer st;
		public FS() {
			br = new BufferedReader(new InputStreamReader(System.in));
		}
		String next() {
			while(st == null || !st.hasMoreElements()) {
				try {st = new StringTokenizer(br.readLine());}
				catch(Exception e) { throw null;}
			}
			return st.nextToken();
		}
		int nextInt() { return Integer.parseInt(next());}
		double nextDouble() { return Double.parseDouble(next());}
		long nextLong() { return Long.parseLong(next());}
		int[] NIA(int n) {
			int r[] = new int[n];
			for(int i = 0; i < n; i++) r[i] = nextInt();
			return r;
		}
		long[] NLA(int n) {
			long r[] = new long[n];
			for(int i = 0; i < n; i++) r[i] = nextLong();
			return r;
		}
		char[][] grid(int r, int c){
			char res[][] = new char[r][c];
			for(int i = 0; i < r; i++) {
				char l[] = next().toCharArray();
				for(int j = 0; j < c; j++) {
					res[i][j] = l[j];
				}
			}
			return res;
		}
	}

}


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.io.IOException;
import java.io.InputStream;
/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        OutputWriter out = new OutputWriter(outputStream);
        ExpectedEarnings solver = new ExpectedEarnings();
        solver.solve(1, in, out);
        out.close();
    }
    static class ExpectedEarnings {
        public void solve(int testNumber, InputReader in, OutputWriter out) {
            int n = in.nextInt(), X = in.nextInt();
            double c = X / 1_000_000.0;
            double[] cprob = new double[n + 1];
            for (int i = 0; i <= n; i++) {
                cprob[i] = in.nextInt();
            }
            double[] dp = new double[n + 1];
            for (int nballs = n - 1; nballs >= 0; nballs--) {
                double[] next = new double[nballs + 1];
                double[] nprob = new double[nballs + 1];
                for (int red = 0; red <= nballs; red++) {
                    if (cprob[red] < 1e-10 && cprob[red + 1] < 1e-10) continue;
                    int black = nballs - red;
                    double probred = cprob[red + 1] * (red + 1) / (cprob[red + 1] * (red + 1) + cprob[red] * (black + 1));
                    nprob[red] = ((red + 1) * cprob[red + 1] + (black + 1) * cprob[red]) / (double) (nballs + 1);
                    next[red] = Math.max(0, -c + probred * (1 + dp[red + 1]) + (1 - probred) * dp[red]);
                }
                dp = next;
                cprob = nprob;
            }
            out.printf("%.10f\n", dp[0]);
        }
    }
    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
        public InputReader(InputStream stream) {
            this.stream = stream;
        }
        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 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 printf(String format, Object... objects) {
            writer.printf(format, objects);
        }
        public void close() {
            writer.close();
        }
    }
}


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

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

class TaskD3 {

    final long MOD = 1_000_003;

    long mul(long a, long b) {
        return a * b % MOD;
    }

    long add(long a, long b) {
        return (a + b) % MOD;
    }

    long[][] mul(long[][] a, long[][] b) {
        int N = a.length;
        int K = a[0].length;
        int M = b[0].length;
        long[][] res = new long[N][M];
        for (int i = 0; i < N; i++)
            for (int j = 0; j < M; j++)
                for (int k = 0; k < K; k++)
                    res[i][j] = add(res[i][j], mul(a[i][k], b[k][j]));
        return res;
    }

    long[][] binPow(long[][] x, long n) {
        long[][] res = new long[x.length][x.length];
        for (int i = 0; i < res.length; i++)
            res[i][i] = 1;
        while (n > 0) {
            if (n % 2 == 1)
                res = mul(res, x);
            x = mul(x, x);
            n /= 2;
        }
        return res;
    }

    public void solve(int testNumber, FastScanner in, PrintWriter out) {
        int c = in.nextInt();
        int w = in.nextInt();
        int h = in.nextInt();
        long[][] x = new long[w + 1][w + 1];
        for (int j = 0; j <= w; j++)
            x[0][j] = 1;
        for (int i = 1; i <= w; i++)
            x[i][i - 1] = h;
        long[][] a = binPow(x, c);
        long[][] v = new long[w + 1][1];
        v[0][0] = 1;
        long[][] res = mul(a, v);
        long ans = 0;
        for (int i = 0; i <= w; i++)
            ans = add(ans, res[i][0]);
        out.println(ans);
    }
}

class FastScanner {
    private StringTokenizer tokenizer;
    private BufferedReader reader;

    public FastScanner(InputStream inputStream) {
        reader = new BufferedReader(new InputStreamReader(inputStream));
    }

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

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

}


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

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

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

    static class DINOIFinalContests {
        int mod;
        Factorial fact;
        Combination comb;
        long[] f;
        long[] g;
        Debug debug = new Debug(true);

        public long g(int n) {
            if (n == 0) {
                return 0;
            }
            if (g[n] == -1) {
                long sum = 0;
                for (int i = 0; i < n; i++) {
                    int left = i;
                    int right = n - 1 - i;
                    //0.. left
                    //0.. right
                    long contrib = (g(left) * f(right) + g(right) * f(left)) % mod * (n - 1 + 2) % mod + f(left) * f(right) % mod * ((IntMath.sumOfInterval(0, left) +
                            IntMath.sumOfInterval(0, right)) % mod) % mod;
                    contrib = contrib % mod * comb.combination(n - 1, left) % mod;
                    sum += contrib;
                }
                g[n] = sum % mod;
            }
            return g[n];
        }

        public long f(int n) {
            if (n == 0) {
                return 1;
            }
            if (f[n] == -1) {
                long sum = 0;
                for (int i = 0; i < n; i++) {
                    int left = i;
                    int right = n - 1 - i;
                    sum += f(left) * comb.combination(n - 1, left) % mod * f(right) % mod * (n - 1 + 2) % mod;
                }
                f[n] = sum % mod;
            }
            return f[n];
        }

        public void solve(int testNumber, FastInput in, FastOutput out) {
            int n = in.readInt();
            int m = in.readInt();
            int p = in.readInt();
            mod = p;
            fact = new Factorial((int) 1e4, p);
            comb = new Combination(fact);

            f = new long[m + 1];
            g = new long[m + 1];
            Arrays.fill(f, -1L);
            Arrays.fill(g, -1L);

            long[][] dpWay = new long[n + 1][m + 1];
            long[][] dpSum = new long[n + 1][m + 1];
            dpWay[0][0] = 1;
            for (int i = 1; i <= n; i++) {
                for (int j = 0; j <= m && j <= i; j++) {
                    dpWay[i][j] = dpWay[i - 1][j];
                    dpSum[i][j] = dpSum[i - 1][j];
                    for (int k = 1; k <= j; k++) {
                        int prev = Math.max(i - k - 1, 0);
                        dpWay[i][j] += dpWay[prev][j - k] * comb.combination(j, k) % mod * f(k) % mod;
                        long local = dpSum[prev][j - k] * f(k) +
                                dpWay[prev][j - k] * g(k);
                        local = local % mod * comb.combination(j, k) % mod;
                        dpSum[i][j] += local;
                    }
                    dpWay[i][j] %= mod;
                    dpSum[i][j] %= mod;
                }
            }

            long ans = dpSum[n][m];
            debug.debug("f", f);
            debug.debug("g", g);
            debug.debug("dpWay", dpWay);
            debug.debug("dpSum", dpSum);
            out.println(ans);
        }

    }

    static class Combination implements IntCombination {
        final Factorial factorial;
        int modVal;

        public Combination(Factorial factorial) {
            this.factorial = factorial;
            this.modVal = factorial.getMod();
        }

        public Combination(int limit, int mod) {
            this(new Factorial(limit, mod));
        }

        public int combination(int m, int n) {
            if (n > m || n < 0) {
                return 0;
            }
            return (int) ((long) factorial.fact(m) * factorial.invFact(n) % modVal * factorial.invFact(m - n) % modVal);
        }

    }

    static class FastOutput implements AutoCloseable, Closeable, Appendable {
        private static final int THRESHOLD = 1 << 13;
        private final Writer os;
        private StringBuilder cache = new StringBuilder(THRESHOLD * 2);

        public FastOutput append(CharSequence csq) {
            cache.append(csq);
            return this;
        }

        public FastOutput append(CharSequence csq, int start, int end) {
            cache.append(csq, start, end);
            return this;
        }

        private void afterWrite() {
            if (cache.length() < THRESHOLD) {
                return;
            }
            flush();
        }

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

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

        public FastOutput append(char c) {
            cache.append(c);
            afterWrite();
            return this;
        }

        public FastOutput append(long c) {
            cache.append(c);
            afterWrite();
            return this;
        }

        public FastOutput append(String c) {
            cache.append(c);
            afterWrite();
            return this;
        }

        public FastOutput println(long c) {
            return append(c).println();
        }

        public FastOutput println() {
            return append(System.lineSeparator());
        }

        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 interface IntCombination {
    }

    static class Factorial {
        int[] fact;
        int[] inv;
        int mod;

        public int getMod() {
            return mod;
        }

        public Factorial(int[] fact, int[] inv, int mod) {
            this.mod = mod;
            this.fact = fact;
            this.inv = inv;
            fact[0] = inv[0] = 1;
            int n = Math.min(fact.length, mod);
            for (int i = 1; i < n; i++) {
                fact[i] = i;
                fact[i] = (int) ((long) fact[i] * fact[i - 1] % mod);
            }
            inv[n - 1] = BigInteger.valueOf(fact[n - 1]).modInverse(BigInteger.valueOf(mod)).intValue();
            for (int i = n - 2; i >= 1; i--) {
                inv[i] = (int) ((long) inv[i + 1] * (i + 1) % mod);
            }
        }

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

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

        public int invFact(int n) {
            return inv[n];
        }

    }

    static class Debug {
        private boolean offline;
        private PrintStream out = System.err;
        static int[] empty = new int[0];

        public Debug(boolean enable) {
            offline = enable && System.getSecurityManager() == null;
        }

        public Debug debug(String name, Object x) {
            return debug(name, x, empty);
        }

        public Debug debug(String name, Object x, int... indexes) {
            if (offline) {
                if (x == null || !x.getClass().isArray()) {
                    out.append(name);
                    for (int i : indexes) {
                        out.printf("[%d]", i);
                    }
                    out.append("=").append("" + x);
                    out.println();
                } else {
                    indexes = Arrays.copyOf(indexes, indexes.length + 1);
                    if (x instanceof byte[]) {
                        byte[] arr = (byte[]) x;
                        for (int i = 0; i < arr.length; i++) {
                            indexes[indexes.length - 1] = i;
                            debug(name, arr[i], indexes);
                        }
                    } else if (x instanceof short[]) {
                        short[] arr = (short[]) x;
                        for (int i = 0; i < arr.length; i++) {
                            indexes[indexes.length - 1] = i;
                            debug(name, arr[i], indexes);
                        }
                    } else if (x instanceof boolean[]) {
                        boolean[] arr = (boolean[]) x;
                        for (int i = 0; i < arr.length; i++) {
                            indexes[indexes.length - 1] = i;
                            debug(name, arr[i], indexes);
                        }
                    } else if (x instanceof char[]) {
                        char[] arr = (char[]) x;
                        for (int i = 0; i < arr.length; i++) {
                            indexes[indexes.length - 1] = i;
                            debug(name, arr[i], indexes);
                        }
                    } else if (x instanceof int[]) {
                        int[] arr = (int[]) x;
                        for (int i = 0; i < arr.length; i++) {
                            indexes[indexes.length - 1] = i;
                            debug(name, arr[i], indexes);
                        }
                    } else if (x instanceof float[]) {
                        float[] arr = (float[]) x;
                        for (int i = 0; i < arr.length; i++) {
                            indexes[indexes.length - 1] = i;
                            debug(name, arr[i], indexes);
                        }
                    } else if (x instanceof double[]) {
                        double[] arr = (double[]) x;
                        for (int i = 0; i < arr.length; i++) {
                            indexes[indexes.length - 1] = i;
                            debug(name, arr[i], indexes);
                        }
                    } else if (x instanceof long[]) {
                        long[] arr = (long[]) x;
                        for (int i = 0; i < arr.length; i++) {
                            indexes[indexes.length - 1] = i;
                            debug(name, arr[i], indexes);
                        }
                    } else {
                        Object[] arr = (Object[]) x;
                        for (int i = 0; i < arr.length; i++) {
                            indexes[indexes.length - 1] = i;
                            debug(name, arr[i], indexes);
                        }
                    }
                }
            }
            return this;
        }

    }

    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 IntMath {
        private IntMath() {
        }

        public static long sumOfInterval(long l, long r) {
            return (r + l) * (r - l + 1) / 2;
        }

    }
}


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

public class E_New_Game_Plus {
    private static final FastReader fs = new FastReader();
    private static final PrintWriter out = new PrintWriter(System.out);

    private static void solve() {
        int n = fs.nextInt(),k = fs.nextInt();
        long[] boss = fs.readlongarray(n);
        rSort(boss);
        PriorityQueue<Long> pq = new PriorityQueue<>(Collections.reverseOrder());
        for(int i = 0; i<k+1; i++) {
        	pq.add(0*1l);
        }
        long ans = 0;
        for(int i = 0; i<n; i++) {
        	long x = pq.remove();
        	ans += x;
        	pq.add(x+boss[i]);
        }
        out.println(ans);
    }

    private static void rSort(long[]a){
        ArrayList<Long> tmp = new ArrayList<>();
        for(long x : a)
            tmp.add(x);
        Collections.sort(tmp);
        Collections.reverse(tmp);
        for(int i = 0; i<tmp.size(); i++)
            a[i] = tmp.get(i);
    }

    public static void main(String[] args) {
        Thread t = new Thread(null, null, "", 1 << 28) {
            public void run() {
                int test_case = 1;
                //test_case = fs.nextInt();
                for (int cs = 1; cs <= test_case; cs++) {
                    solve();
                }
                out.close();
            }
        };
        t.start();
        try {
            t.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private static class FastReader {
        BufferedReader br;
        StringTokenizer st;

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

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

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

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

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

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

        int[] readintarray(int n) {
            int res[] = new int[n];
            for (int i = 0; i < n; i++)
                res[i] = nextInt();
            return res;
        }

        long[] readlongarray(int n) {
            long res[] = new long[n];
            for (int i = 0; i < n; i++)
                res[i] = nextLong();
            return res;
        }
    }

    private static class cf {
        public static int min(int x, int y) {
            return Math.min(x, y);
        }

        public static int max(int x, int y) {
            return Math.max(x, y);
        }

        public static long min(long x, long y) {
            return Math.min(x, y);
        }

        public static long max(long x, long y) {
            return Math.max(x, y);
        }

        public static int abs(int x) {
            return x >= 0 ? x : -x;
        }

        public static long abs(long x) {
            return x >= 0 ? x : -x;
        }

        public static boolean even(int x) {
            return x % 2 == 0 ? true : false;
        }

        public static boolean even(long x) {
            return x % 2 == 0 ? true : false;
        }

        public static int power(int base, int exponent) {
            int res = 1;
            while (exponent > 0) {
                if (!even(exponent))
                    res *= base;
                exponent >>= 1;
                base *= base;
            }
            return res;
        }

        public static long power(long base, long exponent) {
            long res = 1;
            while (exponent > 0) {
                if (!even(exponent))
                    res *= base;
                exponent >>= 1;
                base *= base;
            }
            return res;
        }

        public static long mul(long a, long b, long mod) {
            return (a % mod * b % mod) % mod;
        }

        public static long add(long a, long b, long mod) {
            return (a % mod + b % mod) % mod;
        }

        public static long sub(long a, long b, long mod) {
            return ((a % mod - b % mod) % mod + mod) % mod;
        }

        public static long power(long base, long exponent, long mod) {
            long res = 1;
            base %= mod;
            while (exponent > 0) {
                if (!even(exponent))
                    res = mul(res, base, mod);
                exponent >>= 1;
                base = mul(base, base, mod);
            }
            return res;
        }
    }
}


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

public class E {

    public static void main(String[] args) {
        FastReader scan = new FastReader();
        PrintWriter out = new PrintWriter(System.out);
        Task solver = new Task();
        int t = 1;
        for(int tt = 1; tt <= t; tt++) solver.solve(tt, scan, out);
        out.close();
    }

    static class Task {
        public void solve(int testNumber, FastReader scan, PrintWriter out) {
            int n = scan.nextInt(), k = scan.nextInt();
            PriorityQueue<Long> queue = new PriorityQueue<>(Collections.reverseOrder());
            long ans = 0;
            long[] a = new long[n];
            for(int i = 0; i < n; i++) a[i] = scan.nextLong();
            ruffleSort(a);
            for(int i = 0; i <= k; i++) queue.add(0L);
            for(int i = n - 1; i >= 0; i--) {
                long curr = queue.poll();
                ans += curr;
                queue.add(curr + a[i]);
            }
            out.println(ans);
        }
    }

    static void ruffleSort(int[] a) {
        Random get = new Random();
        for (int i = 0; i < a.length; i++) {
            int r = get.nextInt(a.length);
            int temp = a[i];
            a[i] = a[r];
            a[r] = temp;
        }
        Arrays.sort(a);
    }

    static void ruffleSort(long[] a) {
        Random get = new Random();
        for (int i = 0; i < a.length; i++) {
            int r = get.nextInt(a.length);
            long temp = a[i];
            a[i] = a[r];
            a[r] = temp;
        }
        Arrays.sort(a);
    }

    static class FastReader {
        BufferedReader br;
        StringTokenizer st;

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

        public FastReader(String s) throws FileNotFoundException {
            br = new BufferedReader(new FileReader(new File(s)));
        }

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

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

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

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

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

}


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

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

	int[] next, jj; int l_ = 1;
	int link(int l, int j) { next[l_] = l; jj[l_] = j; return l_++; }
	int[] ao; int n;
	int[] cc;
	void init() {
		int m = n - 1;
		next = new int[1 + m * 2];
		jj = new int[1 + m * 2];
		ao = new int[n];
		cc = new int[n];
	}
	int n_, i_, j_;
	int dfs(int p, int i) {
		int k = 1;
		for (int l = ao[i]; l != 0; l = next[l]) {
			int j = jj[l];
			if (j != p)
				k += dfs(i, j);
		}
		int k_ = Math.min(k, n - k);
		if (n_ < k_) {
			n_ = k_;
			if (k <= n - k) {
				i_ = i;
				j_ = p;
			} else {
				i_ = p;
				j_ = i;
			}
		}
		return k;
	}
	int a, b;
	void dfs_(int p, int i, int c) {
		for (int l = ao[i]; l != 0; l = next[l]) {
			int j = jj[l];
			if (j != p) {
				cc[j] = a;
				println((i + 1) + " " + (j + 1) + " " + (a - c));
				a += b;
			}
		}
		for (int l = ao[i]; l != 0; l = next[l]) {
			int j = jj[l];
			if (j != p)
				dfs_(i, j, cc[j]);
		}
	}
	void main() {
		n = sc.nextInt();
		init();
		for (int h = 0; h < n - 1; h++) {
			int i = sc.nextInt() - 1;
			int j = sc.nextInt() - 1;
			ao[i] = link(ao[i], j);
			ao[j] = link(ao[j], i);
		}
		dfs(-1, 0);
		a = 1; b = 1;
		dfs_(i_, j_, 0);
		a = (n - n_) * 2; b = n - n_;
		println((j_ + 1) + " " + (i_ + 1) + " " + (n - n_));
		dfs_(j_, i_, n - n_);
	}
}


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

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

	int[] next, jj; int l_ = 1;
	int link(int l, int j) { next[l_] = l; jj[l_] = j; return l_++; }
	int[] ao; int n;
	int[] cc;
	void init() {
		int m = n - 1;
		next = new int[1 + m * 2];
		jj = new int[1 + m * 2];
		ao = new int[n];
		cc = new int[n];
	}
	int n_, i_, j_;
	int dfs(int p, int i) {
		int k = 1;
		for (int l = ao[i]; l != 0; l = next[l]) {
			int j = jj[l];
			if (j != p)
				k += dfs(i, j);
		}
		int k_ = Math.min(k, n - k);
		if (n_ < k_) {
			n_ = k_;
			if (k <= n - k) {
				i_ = i;
				j_ = p;
			} else {
				i_ = p;
				j_ = i;
			}
		}
		return k;
	}
	int a, b;
	void dfs_(int p, int i, int c) {
		for (int l = ao[i]; l != 0; l = next[l]) {
			int j = jj[l];
			if (j != p) {
				cc[j] = a;
				println((i + 1) + " " + (j + 1) + " " + (a - c));
				a += b;
			}
		}
		for (int l = ao[i]; l != 0; l = next[l]) {
			int j = jj[l];
			if (j != p)
				dfs_(i, j, cc[j]);
		}
	}
	void main() {
		n = sc.nextInt();
		if (n == 1)
			return;
		init();
		for (int h = 0; h < n - 1; h++) {
			int i = sc.nextInt() - 1;
			int j = sc.nextInt() - 1;
			ao[i] = link(ao[i], j);
			ao[j] = link(ao[j], i);
		}
		dfs(-1, 0);
		a = 1; b = 1;
		dfs_(i_, j_, 0);
		a = (n - n_) * 2; b = n - n_;
		println((j_ + 1) + " " + (i_ + 1) + " " + (n - n_));
		dfs_(j_, i_, n - n_);
	}
}


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

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

	int[] next, jj; int l_ = 1;
	int link(int l, int j) { next[l_] = l; jj[l_] = j; return l_++; }
	int[] ao; int n;
	int[] cc;
	void init() {
		int m = n - 1;
		next = new int[1 + m * 2];
		jj = new int[1 + m * 2];
		ao = new int[n];
		cc = new int[n];
	}
	int n_, i_, j_;
	int dfs(int p, int i) {
		int k = 1;
		for (int l = ao[i]; l != 0; l = next[l]) {
			int j = jj[l];
			if (j != p)
				k += dfs(i, j);
		}
		int k_ = Math.min(k, n - k);
		if (n_ < k_) {
			n_ = k_;
			if (k <= n - k) {
				i_ = i;
				j_ = p;
			} else {
				i_ = p;
				j_ = i;
			}
		}
		cc[i] = k;
		return k;
	}
	int a, b;
	void dfs_(int p, int i, int c, boolean print) {
		if (print) {
			a += b;
			println((p + 1) + " " + (i + 1) + " " + (a - c));
			c = a;
		}
		for (int l = ao[i]; l != 0; l = next[l]) {
			int j = jj[l];
			if (j != p)
				dfs_(i, j, c, true);
		}
	}
	void main() {
		n = sc.nextInt();
		if (n == 1)
			return;
		init();
		for (int h = 0; h < n - 1; h++) {
			int i = sc.nextInt() - 1;
			int j = sc.nextInt() - 1;
			ao[i] = link(ao[i], j);
			ao[j] = link(ao[j], i);
		}
		dfs(-1, 0);
		if (n_ * 3 >= n) {
			b = 1;
			a = 0;
			dfs_(i_, j_, 0, false);
			b = n - n_;
			a = 0;
			dfs_(j_, i_, 0, true);
		} else {
			int s = j_;
			dfs(-1, s);
			Integer[] tt = new Integer[n];
			int cnt = 0;
			for (int l = ao[s]; l != 0; l = next[l])
				tt[cnt++] = jj[l];
			Arrays.sort(tt, 0, cnt, (i, j) -> cc[i] - cc[j]);
			n_ = 1;
			b = 1;
			a = 0;
			boolean changed = false;
			for (int h = 0; h < cnt; h++) {
				int j = tt[h];
				n_ += cc[j];
				dfs_(s, j, 0, true);
				if (!changed && n_ * 3 >= n) {
					changed = true;
					b = n_;
					a = 0;
				}
			}
		}
	}
}


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

public class Main {

    static int n, f[];
    static String s;
    static long ans, dp[][][];

    private static void build() {
        // build failure function F[i] = index of largest prefix/suffix with end < i = where to look if i doesn't match
        f[0] = -1;
        f[1] = 0;
        for(int i = 2; i <= s.length(); i++) {
            f[i] = f[i-1];
            while(f[i] != -1 && s.charAt(i-1) != s.charAt(f[i])) f[i] = f[f[i]];
            ++f[i]; // ++ because this is on the scale of i-2 and not i-1
        }
    }

    private static int getNext(int state, char val) {
        if(state == s.length()) return getNext(f[state], val);
        int nxt = state;
        while(nxt != -1 && s.charAt(nxt) != val) nxt = f[nxt];
        return nxt + 1;
    }

    private static long calc(int n, int curr, int start, int done) {
        if(curr == s.length()) done = 1;
        if(n == 0) return (curr == start && done == 1 ? 1 : 0);

        if(dp[n][curr][done] != -1) return dp[n][curr][done];
        dp[n][curr][done] = 0;
        int nxt0 = getNext(curr, '0');
        int nxt1 = getNext(curr, '1');
        dp[n][curr][done] += calc(n-1, nxt0, start, done);
        dp[n][curr][done] += calc(n-1, nxt1, start, done);
        return dp[n][curr][done];
    }

    private static long solve(int starting_state) {
        dp = new long[n + 1][s.length() + 1][2];
        for(long[][] r1: dp) {
            for (long[] r2 : r1)
                Arrays.fill(r2, -1);
        }
        return calc(n, starting_state, starting_state, 0);
    }

    public static void main(String[] args) {
        InputReader cin = new InputReader(System.in);
        n = cin.nextInt();
        s = cin.next();
        f = new int[s.length() + 1];
        ans = 0;

        build();
        for(int starting_state = 0; starting_state <= s.length(); starting_state++) {
            ans += solve(starting_state);
        }

        System.out.println(ans);
    }

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

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

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

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


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

import static java.util.Arrays.fill;

/**
 * @author Don Li
 */
public class WrapAround2 {

    int N = 41;

    int n, m;
    char[] s;

    int[] f;
    long[][][][] dp = new long[N][N][N][2];

    void solve() {
        n = in.nextInt();
        s = in.nextToken().toCharArray();
        m = s.length;

        f = fail(s);

        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) for (int k = 0; k < N; k++) fill(dp[i][j][k], -1);

        long ans = 0;
        for (int i = 0; i <= m; i++) {
            ans += dfs(n, i, i, 0);
        }
        out.println(ans);
    }

    long dfs(int rem, int cur, int tar, int has) {
        if (cur == m) has = 1;

        if (rem == 0) {
            return cur == tar && has > 0 ? 1 : 0;
        }

        if (dp[rem][cur][tar][has] >= 0) return dp[rem][cur][tar][has];

        long ans = 0;
        for (char x = '0'; x <= '1'; x++) {
            int nxt = next(cur, x);
            ans += dfs(rem - 1, nxt, tar, has);
        }
        return dp[rem][cur][tar][has] = ans;
    }

    int next(int now, char x) {
        if (now == m) now = f[now];
        while (now > 0 && s[now] != x) now = f[now];
        return s[now] == x ? now + 1 : 0;
    }

    int[] fail(char[] s) {
        int n = s.length;
        int[] f = new int[n + 1];
        f[0] = f[1] = 0;
        for (int i = 2; i <= n; i++) {
            int j = f[i - 1];
            while (j > 0 && s[j] != s[i - 1]) j = f[j];
            f[i] = s[j] == s[i - 1] ? j + 1 : 0;
        }
        return f;
    }

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

    static FastScanner in;
    static PrintWriter out;

    static class FastScanner {
        BufferedReader in;
        StringTokenizer st;

        public FastScanner(BufferedReader in) {
            this.in = in;
        }

        public String nextToken() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(in.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

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

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

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


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

public class Main {

    static int n, f[];
    static String s;
    static long ans, dp[][];

    public static void main(String[] args) {
        InputReader cin = new InputReader(System.in);
        n = cin.nextInt();
        s = cin.next();
        f = new int[s.length() + 1];
        ans = 0;

        // build failure function F[i] = index of largest prefix/suffix with end < i = where to look if i doesn't match
        f[0] = -1;
        f[1] = 0;
        for(int i = 2; i <= s.length(); i++) {
            f[i] = f[i-1];
            while(f[i] != -1 && s.charAt(i-1) != s.charAt(f[i])) f[i] = f[f[i]];
            ++f[i]; // ++ because this is on the scale of i-2 and not i-1
        }

        for(int suff_len = 0; suff_len < s.length(); suff_len++) {

            // calculate initial next state
            int pref = 0;
            for(int i = s.length() - suff_len; i < s.length(); i++) {
               while(pref != -1 && s.charAt(i) != s.charAt(pref)) pref = f[pref];
               ++pref;
            }

            dp = new long[n + 1][s.length() + 1]; // dp[i][index to look for i+1]

            // base case
            dp[suff_len][pref + 1] = 1;
            int tmp = pref;
            char val = s.charAt(pref) == '0' ? '1' : '0';
            while(tmp != -1 && s.charAt(tmp) != val) tmp = f[tmp];
            dp[suff_len][tmp + 1] = 1;

            for(int i = suff_len; i < n - 1; i++) {
                for(int state = 0; state < s.length(); state++) {
                   dp[i + 1][state + 1] += dp[i][state];
                   tmp = state;
                   val = s.charAt(state) == '0' ? '1' : '0';
                   while(tmp != -1 && s.charAt(tmp) != val) tmp = f[tmp];
                   dp[i + 1][tmp + 1] += dp[i][state];
                }
                dp[i + 1][s.length()] += dp[i][s.length()] << 1;
            }
            ans += dp[n - 1][s.length() - suff_len];
        }
        System.out.println(ans);
    }

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

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

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

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


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

public class Main {

    static int n, f[];
    static String s;
    static long ans, dp[][];

    public static void main(String[] args) {
        InputReader cin = new InputReader(System.in);
        n = cin.nextInt();
        s = cin.next();
        f = new int[s.length() + 1];
        ans = 0;

        // build failure function F[i] = index of largest prefix/suffix with end < i = where to look if i doesn't match
        f[0] = -1;
        f[1] = 0;
        for(int i = 2; i <= s.length(); i++) {
            f[i] = f[i-1];
            while(f[i] != -1 && s.charAt(i-1) != s.charAt(f[i])) f[i] = f[f[i]];
            ++f[i]; // ++ because this is on the scale of i-2 and not i-1
//            System.out.println("f[i] " + i + " " + f[i]);
        }

        for(int suff_len = 0; suff_len < s.length(); suff_len++) {

            // calculate initial next state
            int pref = 0;
            for(int i = s.length() - suff_len; i < s.length(); i++) {
               while(pref != -1 && s.charAt(i) != s.charAt(pref)) pref = f[pref];
               ++pref;
            }

            dp = new long[n + 1][s.length() + 1]; // dp[i][index to look for i+1]

            // base case
            dp[suff_len][pref + 1] = 1;
            int tmp = pref;
            char val = s.charAt(pref) == '0' ? '1' : '0';
            while(tmp != -1 && s.charAt(tmp) != val) tmp = f[tmp];
            dp[suff_len][tmp + 1] = 1;

            for(int i = suff_len; i < n - 1; i++) {
                for(int state = 0; state < s.length(); state++) {
                   dp[i + 1][state + 1] += dp[i][state];
                   tmp = state;
                   val = s.charAt(state) == '0' ? '1' : '0';
                   while(tmp != -1 && s.charAt(tmp) != val) tmp = f[tmp];
                   dp[i + 1][tmp + 1] += dp[i][state];
                }
                if(suff_len == 0) dp[i + 1][s.length()] += dp[i][s.length()] << 1;
            }
//            for(int i = suff_len; i < n; i++) {
//                for(int state = 0; state <= s.length(); state++) {
//                    System.out.println("dp " + i + " " + state + " " + dp[i][state]);
//                }
//            }
            for(int i = s.length() - 1; i > 0; i--) {
                if(f[i] > 0 && s.charAt(f[i] - 1) == s.charAt(i - 1))
                    dp[n - 1][f[i]] += dp[n - 1][i];
            }
            ans += dp[n - 1][s.length() - suff_len];

//            System.out.println("answer " + suff_len + " " + (s.length() - suff_len) + " " + pref + " " + dp[n - 1][s.length() - suff_len]);
        }
        System.out.println(ans);
    }

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

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

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

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


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Deque;
import java.util.function.Supplier;
import java.io.OutputStreamWriter;
import java.math.BigInteger;
import java.io.OutputStream;
import java.util.Collection;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.function.Consumer;
import java.io.Closeable;
import java.io.Writer;
import java.util.ArrayDeque;
import java.io.InputStream;

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

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

    static class ETransformingSequence {
        int mod = (int) 1e9 + 7;
        IntPoly poly = new IntPolyFFT(mod);
        Factorial fact = new Factorial((int) 1e5, mod);
        CachedPow pow = new CachedPow(2, mod);
        Combination comb = new Combination(fact);

        public void solve(int testNumber, FastInput in, FastOutput out) {
            long n = in.readLong();
            int k = in.readInt();
            if (n > k) {
                out.println(0);
                return;
            }

            int[] x = new int[k + 1];
            Arrays.fill(x, 1, k + 1, 1);
            int[] ans = pow(x, (int) n);
            long sum = 0;
            for (int i = 0; i <= k; i++) {
                sum += (long) ans[i] * comb.combination(k, i) % mod;
            }
            sum %= mod;
            out.println(sum);
        }

        public int[] mul(int[] dpL, int[] dpR, int l, int r) {
            int n = dpL.length;
            int[] f = PrimitiveBuffers.allocIntPow2(n);
            int[] g = PrimitiveBuffers.allocIntPow2(n);
            for (int i = 0; i < n; i++) {
                f[i] = (int) ((long) dpL[i] * fact.invFact(i) % mod * pow.pow((long) r * i) % mod);
                g[i] = (int) ((long) dpR[i] * fact.invFact(i) % mod);
            }
            int[] ans = poly.convolution(f, g);
            int[] ret = Arrays.copyOf(ans, n);
            for (int i = 0; i < n; i++) {
                ret[i] = (int) ((long) ret[i] * fact.fact(i) % mod);
            }
            PrimitiveBuffers.release(f, g, ans);
            return ret;
        }

        public int[] pow(int[] x, int n) {
            if (n == 0) {
                int[] ans = new int[x.length];
                ans[0] = 1;
                return ans;
            }
            int[] ans = pow(x, n / 2);
            ans = mul(ans, ans, n / 2, n / 2);
            if (n % 2 == 1) {
                ans = mul(ans, x, n - 1, 1);
            }
            return ans;
        }

    }

    static class Log2 {
        public static int ceilLog(int x) {
            if (x <= 0) {
                return 0;
            }
            return 32 - Integer.numberOfLeadingZeros(x - 1);
        }

    }

    static class IntPoly {
        protected int mod;
        protected Power power;

        public IntPoly(int mod) {
            this.mod = mod;
            this.power = new Power(mod);
        }

        public int[] convolution(int[] a, int[] b) {
            return mulBF(a, b);
        }

        public int rankOf(int[] p) {
            int r = p.length - 1;
            while (r >= 0 && p[r] == 0) {
                r--;
            }
            return Math.max(0, r);
        }

        public int[] mulBF(int[] a, int[] b) {
            int rA = rankOf(a);
            int rB = rankOf(b);
            if (rA > rB) {
                {
                    int tmp = rA;
                    rA = rB;
                    rB = tmp;
                }
                {
                    int[] tmp = a;
                    a = b;
                    b = tmp;
                }
            }
            int[] c = PrimitiveBuffers.allocIntPow2(rA + rB + 1);
            for (int i = 0; i <= rA; i++) {
                for (int j = 0; j <= rB; j++) {
                    c[i + j] = (int) ((c[i + j] + (long) a[i] * b[j]) % mod);
                }
            }
            return c;
        }

    }

    static class Factorial {
        int[] fact;
        int[] inv;
        int mod;

        public int getMod() {
            return mod;
        }

        public Factorial(int[] fact, int[] inv, int mod) {
            this.mod = mod;
            this.fact = fact;
            this.inv = inv;
            fact[0] = inv[0] = 1;
            int n = Math.min(fact.length, mod);
            for (int i = 1; i < n; i++) {
                fact[i] = i;
                fact[i] = (int) ((long) fact[i] * fact[i - 1] % mod);
            }
            inv[n - 1] = BigInteger.valueOf(fact[n - 1]).modInverse(BigInteger.valueOf(mod)).intValue();
            for (int i = n - 2; i >= 1; i--) {
                inv[i] = (int) ((long) inv[i + 1] * (i + 1) % mod);
            }
        }

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

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

        public int invFact(int n) {
            return inv[n];
        }

    }

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

        public long readLong() {
            int sign = 1;

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

            long 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 DigitUtils {
        private DigitUtils() {
        }

        public static int mod(long x, int mod) {
            if (x < -mod || x >= mod) {
                x %= mod;
            }
            if (x < 0) {
                x += mod;
            }
            return (int) x;
        }

        public static int mod(int x, int mod) {
            if (x < -mod || x >= mod) {
                x %= mod;
            }
            if (x < 0) {
                x += mod;
            }
            return x;
        }

    }

    static class Power implements InverseNumber {
        int mod;

        public Power(Modular modular) {
            this.mod = modular.getMod();
        }

        public Power(int mod) {
            this(new Modular(mod));
        }

    }

    static interface IntCombination {
    }

    static class FastOutput implements AutoCloseable, Closeable, Appendable {
        private static final int THRESHOLD = 1 << 13;
        private final Writer os;
        private StringBuilder cache = new StringBuilder(THRESHOLD * 2);

        public FastOutput append(CharSequence csq) {
            cache.append(csq);
            return this;
        }

        public FastOutput append(CharSequence csq, int start, int end) {
            cache.append(csq, start, end);
            return this;
        }

        private void afterWrite() {
            if (cache.length() < THRESHOLD) {
                return;
            }
            flush();
        }

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

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

        public FastOutput append(char c) {
            cache.append(c);
            afterWrite();
            return this;
        }

        public FastOutput append(int c) {
            cache.append(c);
            afterWrite();
            return this;
        }

        public FastOutput append(long c) {
            cache.append(c);
            afterWrite();
            return this;
        }

        public FastOutput append(String c) {
            cache.append(c);
            afterWrite();
            return this;
        }

        public FastOutput println(int c) {
            return append(c).println();
        }

        public FastOutput println(long c) {
            return append(c).println();
        }

        public FastOutput println() {
            return append(System.lineSeparator());
        }

        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 CachedPow {
        private int[] first;
        private int[] second;
        private int mod;
        private int powMod;
        private static int step = 16;
        private static int limit = 1 << step;
        private static int mask = limit - 1;

        public CachedPow(int x, int mod) {
            this.mod = mod;
            this.powMod = mod - 1;
            first = new int[limit];
            second = new int[Integer.MAX_VALUE / limit + 1];
            first[0] = 1;
            for (int i = 1; i < first.length; i++) {
                first[i] = (int) ((long) x * first[i - 1] % mod);
            }
            second[0] = 1;
            long step = (long) x * first[first.length - 1] % mod;
            for (int i = 1; i < second.length; i++) {
                second[i] = (int) (second[i - 1] * step % mod);
            }
        }

        public int pow(int exp) {
            return (int) ((long) first[exp & mask] * second[exp >> step] % mod);
        }

        public int pow(long exp) {
            return pow(DigitUtils.mod(exp, powMod));
        }

    }

    static class Combination implements IntCombination {
        final Factorial factorial;
        int modVal;

        public Combination(Factorial factorial) {
            this.factorial = factorial;
            this.modVal = factorial.getMod();
        }

        public Combination(int limit, int mod) {
            this(new Factorial(limit, mod));
        }

        public int combination(int m, int n) {
            if (n > m || n < 0) {
                return 0;
            }
            return (int) ((long) factorial.fact(m) * factorial.invFact(n) % modVal * factorial.invFact(m - n) % modVal);
        }

    }

    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 String toString() {
            return "mod " + m;
        }

    }

    static class PrimitiveBuffers {
        public static Buffer<int[]>[] intPow2Bufs = new Buffer[30];
        public static Buffer<double[]>[] doublePow2Bufs = new Buffer[30];

        static {
            for (int i = 0; i < 30; i++) {
                int finalI = i;
                intPow2Bufs[i] = new Buffer<>(() -> new int[1 << finalI], x -> Arrays.fill(x, 0));
                doublePow2Bufs[i] = new Buffer<>(() -> new double[1 << finalI], x -> Arrays.fill(x, 0));
            }
        }

        public static int[] allocIntPow2(int n) {
            return intPow2Bufs[Log2.ceilLog(n)].alloc();
        }

        public static void release(int[] data) {
            intPow2Bufs[Log2.ceilLog(data.length)].release(data);
        }

        public static void release(int[] a, int[] b, int[] c) {
            release(a);
            release(b);
            release(c);
        }

        public static double[] allocDoublePow2(int n) {
            return doublePow2Bufs[Log2.ceilLog(n)].alloc();
        }

        public static double[] allocDoublePow2(double[] data, int newLen) {
            double[] ans = allocDoublePow2(newLen);
            System.arraycopy(data, 0, ans, 0, Math.min(data.length, newLen));
            return ans;
        }

        public static void release(double[] data) {
            doublePow2Bufs[Log2.ceilLog(data.length)].release(data);
        }

        public static void release(double[]... data) {
            for (double[] x : data) {
                release(x);
            }
        }

    }

    static interface InverseNumber {
    }

    static class FastFourierTransform {
        private static double[][] realLevels = new double[30][];
        private static double[][] imgLevels = new double[30][];

        private static void prepareLevel(int i) {
            if (realLevels[i] == null) {
                realLevels[i] = new double[1 << i];
                imgLevels[i] = new double[1 << i];
                for (int j = 0, s = 1 << i; j < s; j++) {
                    realLevels[i][j] = Math.cos(Math.PI / s * j);
                    imgLevels[i][j] = Math.sin(Math.PI / s * j);
                }
            }
        }

        public static void fft(double[][] p, boolean inv) {
            int m = Log2.ceilLog(p[0].length);
            int n = 1 << m;
            int shift = 32 - Integer.numberOfTrailingZeros(n);
            for (int i = 1; i < n; i++) {
                int j = Integer.reverse(i << shift);
                if (i < j) {
                    SequenceUtils.swap(p[0], i, j);
                    SequenceUtils.swap(p[1], i, j);
                }
            }

            double[][] t = new double[2][1];
            for (int d = 0; d < m; d++) {
                int s = 1 << d;
                int s2 = s << 1;
                prepareLevel(d);
                for (int i = 0; i < n; i += s2) {
                    for (int j = 0; j < s; j++) {
                        int a = i + j;
                        int b = a + s;
                        mul(realLevels[d][j], imgLevels[d][j], p[0][b], p[1][b], t, 0);
                        sub(p[0][a], p[1][a], t[0][0], t[1][0], p, b);
                        add(p[0][a], p[1][a], t[0][0], t[1][0], p, a);
                    }
                }
            }

            if (inv) {
                for (int i = 0, j = 0; i <= j; i++, j = n - i) {
                    double a = p[0][j];
                    double b = p[1][j];
                    div(p[0][i], p[1][i], n, p, j);
                    if (i != j) {
                        div(a, b, n, p, i);
                    }
                }
            }
        }

        public static void add(double r1, double i1, double r2, double i2, double[][] r, int i) {
            r[0][i] = r1 + r2;
            r[1][i] = i1 + i2;
        }

        public static void sub(double r1, double i1, double r2, double i2, double[][] r, int i) {
            r[0][i] = r1 - r2;
            r[1][i] = i1 - i2;
        }

        public static void mul(double r1, double i1, double r2, double i2, double[][] r, int i) {
            r[0][i] = r1 * r2 - i1 * i2;
            r[1][i] = r1 * i2 + i1 * r2;
        }

        public static void div(double r1, double i1, double r2, double[][] r, int i) {
            r[0][i] = r1 / r2;
            r[1][i] = i1 / r2;
        }

    }

    static class SequenceUtils {
        public static void swap(double[] data, int i, int j) {
            double tmp = data[i];
            data[i] = data[j];
            data[j] = tmp;
        }

    }

    static class Buffer<T> {
        private Deque<T> deque;
        private Supplier<T> supplier;
        private Consumer<T> cleaner;
        private int allocTime;
        private int releaseTime;

        public Buffer(Supplier<T> supplier) {
            this(supplier, (x) -> {
            });
        }

        public Buffer(Supplier<T> supplier, Consumer<T> cleaner) {
            this(supplier, cleaner, 0);
        }

        public Buffer(Supplier<T> supplier, Consumer<T> cleaner, int exp) {
            this.supplier = supplier;
            this.cleaner = cleaner;
            deque = new ArrayDeque<>(exp);
        }

        public T alloc() {
            allocTime++;
            return deque.isEmpty() ? supplier.get() : deque.removeFirst();
        }

        public void release(T e) {
            releaseTime++;
            cleaner.accept(e);
            deque.addLast(e);
        }

    }

    static class IntPolyFFT extends IntPoly {
        private static final int FFT_THRESHOLD = 50;

        public IntPolyFFT(int mod) {
            super(mod);
        }

        public int[] convolution(int[] a, int[] b) {
            if (a != b) {
                return multiplyMod(a, b);
            } else {
                return pow2(a);
            }
        }

        public int[] pow2(int[] a) {
            int rA = rankOf(a);
            if (rA < FFT_THRESHOLD) {
                return mulBF(a, a);
            }

            int need = rA * 2 + 1;

            double[] aReal = PrimitiveBuffers.allocDoublePow2(need);
            double[] aImag = PrimitiveBuffers.allocDoublePow2(need);
            int n = aReal.length;

            for (int i = 0; i <= rA; i++) {
                int x = DigitUtils.mod(a[i], mod);
                aReal[i] = x & ((1 << 15) - 1);
                aImag[i] = x >> 15;
            }
            FastFourierTransform.fft(new double[][]{aReal, aImag}, false);

            double[] bReal = PrimitiveBuffers.allocDoublePow2(aReal, aReal.length);
            double[] bImag = PrimitiveBuffers.allocDoublePow2(aImag, bReal.length);

            for (int i = 0, j = 0; i <= j; i++, j = n - i) {
                double ari = aReal[i];
                double aii = aImag[i];
                double bri = bReal[i];
                double bii = bImag[i];
                double arj = aReal[j];
                double aij = aImag[j];
                double brj = bReal[j];
                double bij = bImag[j];

                double a1r = (ari + arj) / 2;
                double a1i = (aii - aij) / 2;
                double a2r = (aii + aij) / 2;
                double a2i = (arj - ari) / 2;

                double b1r = (bri + brj) / 2;
                double b1i = (bii - bij) / 2;
                double b2r = (bii + bij) / 2;
                double b2i = (brj - bri) / 2;

                aReal[i] = a1r * b1r - a1i * b1i - a2r * b2i - a2i * b2r;
                aImag[i] = a1r * b1i + a1i * b1r + a2r * b2r - a2i * b2i;
                bReal[i] = a1r * b2r - a1i * b2i + a2r * b1r - a2i * b1i;
                bImag[i] = a1r * b2i + a1i * b2r + a2r * b1i + a2i * b1r;

                if (i != j) {
                    a1r = (arj + ari) / 2;
                    a1i = (aij - aii) / 2;
                    a2r = (aij + aii) / 2;
                    a2i = (ari - arj) / 2;

                    b1r = (brj + bri) / 2;
                    b1i = (bij - bii) / 2;
                    b2r = (bij + bii) / 2;
                    b2i = (bri - brj) / 2;

                    aReal[j] = a1r * b1r - a1i * b1i - a2r * b2i - a2i * b2r;
                    aImag[j] = a1r * b1i + a1i * b1r + a2r * b2r - a2i * b2i;
                    bReal[j] = a1r * b2r - a1i * b2i + a2r * b1r - a2i * b1i;
                    bImag[j] = a1r * b2i + a1i * b2r + a2r * b1i + a2i * b1r;
                }
            }

            FastFourierTransform.fft(new double[][]{aReal, aImag}, true);
            FastFourierTransform.fft(new double[][]{bReal, bImag}, true);

            int[] ans = PrimitiveBuffers.allocIntPow2(need);
            for (int i = 0; i < need; i++) {
                long aa = DigitUtils.mod(Math.round(aReal[i]), mod);
                long bb = DigitUtils.mod(Math.round(bReal[i]), mod);
                long cc = DigitUtils.mod(Math.round(aImag[i]), mod);
                ans[i] = DigitUtils.mod(aa + (bb << 15) + (cc << 30), mod);
            }

            PrimitiveBuffers.release(aReal, bReal, aImag, bImag);
            return ans;
        }

        private int[] multiplyMod(int[] a, int[] b) {
            int rA = rankOf(a);
            int rB = rankOf(b);
            if (Math.min(rA, rB) < FFT_THRESHOLD) {
                return mulBF(a, b);
            }

            int need = rA + rB + 1;

            double[] aReal = PrimitiveBuffers.allocDoublePow2(need);
            double[] aImag = PrimitiveBuffers.allocDoublePow2(need);
            int n = aReal.length;

            for (int i = 0; i <= rA; i++) {
                int x = DigitUtils.mod(a[i], mod);
                aReal[i] = x & ((1 << 15) - 1);
                aImag[i] = x >> 15;
            }
            FastFourierTransform.fft(new double[][]{aReal, aImag}, false);

            double[] bReal = PrimitiveBuffers.allocDoublePow2(need);
            double[] bImag = PrimitiveBuffers.allocDoublePow2(need);
            for (int i = 0; i <= rB; i++) {
                int x = DigitUtils.mod(b[i], mod);
                bReal[i] = x & ((1 << 15) - 1);
                bImag[i] = x >> 15;
            }
            FastFourierTransform.fft(new double[][]{bReal, bImag}, false);

            for (int i = 0, j = 0; i <= j; i++, j = n - i) {
                double ari = aReal[i];
                double aii = aImag[i];
                double bri = bReal[i];
                double bii = bImag[i];
                double arj = aReal[j];
                double aij = aImag[j];
                double brj = bReal[j];
                double bij = bImag[j];

                double a1r = (ari + arj) / 2;
                double a1i = (aii - aij) / 2;
                double a2r = (aii + aij) / 2;
                double a2i = (arj - ari) / 2;

                double b1r = (bri + brj) / 2;
                double b1i = (bii - bij) / 2;
                double b2r = (bii + bij) / 2;
                double b2i = (brj - bri) / 2;

                aReal[i] = a1r * b1r - a1i * b1i - a2r * b2i - a2i * b2r;
                aImag[i] = a1r * b1i + a1i * b1r + a2r * b2r - a2i * b2i;
                bReal[i] = a1r * b2r - a1i * b2i + a2r * b1r - a2i * b1i;
                bImag[i] = a1r * b2i + a1i * b2r + a2r * b1i + a2i * b1r;

                if (i != j) {
                    a1r = (arj + ari) / 2;
                    a1i = (aij - aii) / 2;
                    a2r = (aij + aii) / 2;
                    a2i = (ari - arj) / 2;

                    b1r = (brj + bri) / 2;
                    b1i = (bij - bii) / 2;
                    b2r = (bij + bii) / 2;
                    b2i = (bri - brj) / 2;

                    aReal[j] = a1r * b1r - a1i * b1i - a2r * b2i - a2i * b2r;
                    aImag[j] = a1r * b1i + a1i * b1r + a2r * b2r - a2i * b2i;
                    bReal[j] = a1r * b2r - a1i * b2i + a2r * b1r - a2i * b1i;
                    bImag[j] = a1r * b2i + a1i * b2r + a2r * b1i + a2i * b1r;
                }
            }

            FastFourierTransform.fft(new double[][]{aReal, aImag}, true);
            FastFourierTransform.fft(new double[][]{bReal, bImag}, true);

            int[] ans = PrimitiveBuffers.allocIntPow2(need);
            for (int i = 0; i < need; i++) {
                long aa = DigitUtils.mod(Math.round(aReal[i]), mod);
                long bb = DigitUtils.mod(Math.round(bReal[i]), mod);
                long cc = DigitUtils.mod(Math.round(aImag[i]), mod);
                ans[i] = DigitUtils.mod(aa + (bb << 15) + (cc << 30), mod);
            }

            PrimitiveBuffers.release(aReal, bReal, aImag, bImag);
            return ans;
        }

    }
}