import static java.lang.Integer.parseInt;
import static java.lang.Long.parseLong;
import static java.lang.System.exit;
import static java.util.Arrays.fill;

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

public class Codeforces {

	interface IntComparator {
		public int compare(int o1, int o2);
	}

	static void sort(int a[], int n, IntComparator cmp) {
		if (n == 0) {
			return;
		}
		for (int i = 1; i < n; i++) {
			int j = i;
			int ca = a[i];
			do {
				int nj = (j - 1) >> 1;
				int na = a[nj];
				if (cmp.compare(na, ca) >= 0) {
					break;
				}
				a[j] = na;
				j = nj;
			} while (j != 0);
			a[j] = ca;
		}
		int ca = a[0];
		for (int i = n - 1; i > 0; i--) {
			int j = 0;
			while ((j << 1) + 2 + Integer.MIN_VALUE < i + Integer.MIN_VALUE) {
				j <<= 1;
				j += (cmp.compare(a[j + 1], a[j + 2]) < 0) ? 2 : 1;
			}
			if ((j << 1) + 2 == i) {
				j = (j << 1) + 1;
			}
			int na = a[i];
			a[i] = ca;
			ca = na;
			while (j != 0 && cmp.compare(a[j], ca) < 0) {
				j = (j - 1) >> 1;
			}
			while (j != 0) {
				na = a[j];
				a[j] = ca;
				ca = na;
				j = (j - 1) >> 1;
			}
		}
		a[0] = ca;
	}

	static int n, k, a[], sum, move[], moveOffset, defer[], deferCnt, derefFirst[];

	static void doMove(int pos) {
		if (a[pos] < (move[(pos + 1) % n] - moveOffset) || a[(pos + k - 1) % n] < -(move[(pos + k - 1) % n] - moveOffset)) {
			if (deferCnt == 0) {
				derefFirst = new int[k - 1];
				for (int i = 0; i < k - 1; i++) {
					derefFirst[i] = move[(pos + i + 1) % n] - moveOffset;
					move[(pos + i + 1) % n] = moveOffset;
				}
			}
			defer[deferCnt++] = pos;
			return;
		}
		for (int i = 0; i < k - 1; i++) {
			int m = move[(pos + i + 1) % n] - moveOffset;
			a[(pos + i) % n] -= m;
			a[(pos + i + 1) % n] += m;
			move[(pos + i + 1) % n] = moveOffset;
		}
		out.print(pos);
		for (int i = 0; i < k; i++) {
			out.print(" " + a[(pos + i) % n]);
		}
		out.println();
		if (deferCnt > 0) {
			if (--deferCnt == 0) {
				pos = defer[0];
				for (int i = 0; i < k - 1; i++) {
					int m = derefFirst[i];
					a[(pos + i) % n] -= m;
					a[(pos + i + 1) % n] += m;
				}
				out.print(pos);
				for (int i = 0; i < k; i++) {
					out.print(" " + a[(pos + i) % n]);
				}
				out.println();
			} else {
				doMove(defer[deferCnt]);
			}
		}
	}

	static void solve() throws Exception {
		n = scanInt();
		k = scanInt();
		a = new int[n];
		sum = 0;
		for (int i = 0; i < n; i++) {
			sum += a[i] = scanInt();
		}
		sum /= n;
		move = new int[n];
		int idx[] = new int[n];
		for (int i = 0; i < n - 1; i++) {
			move[i + 1] = move[i] + a[i] - sum;
			idx[i] = i;
		}
		idx[n - 1] = n - 1;
		sort(idx, n, new IntComparator() {
			public int compare(int o1, int o2) {
				return move[o1] != move[o2] ? move[o1] - move[o2] : o1 - o2;
			}
		});
		int ans = (n + k - 2) / (k - 1), ansStart = -1;
		int maxChain[] = new int[n], curNext[] = new int[k - 1];
		fill(curNext, -1);
		for (int i = 0, j; i < n; i = j) {
			for (j = i + 1; j < n && move[idx[j]] == move[idx[i]]; j++) { }
			for (int ii = j - 1; ii >= i; ii--) {
				int ci = idx[ii], ni = curNext[(ci + 1) % (k - 1)];
//				System.err.println(ci + " " + ni);
				maxChain[ci] = ni < 0 ? 1 : 1 + maxChain[ni];
				int cans = (n - maxChain[ci] + k - 2) / (k - 1);
				if (cans < ans) {
					ans = cans;
					ansStart = ci;
				}
				curNext[ci % (k - 1)] = ci;
			}
			for (int ii = i; ii < j; ii++) {
				curNext[idx[ii] % (k - 1)] = -1;
			}
		}
//		System.err.println(Arrays.toString(maxChain));
		out.println(ans);
		defer = new int[n];
		deferCnt = 0;
//		System.err.println(ans + " " + ansStart + " " + sum);
		if (ansStart < 0) {
			moveOffset = 0;
			for (int i = 0; i < ans; i++) {
				doMove(i * (k - 1));
			}
		} else {
			moveOffset = move[ansStart];
//			System.err.println(Arrays.toString(move) + " " + moveOffset);
			for (int i = 0, pos = ansStart; i < ans; i++) {
				while (move[(pos + 1) % n] == moveOffset) {
					pos = (pos + 1) % n;
				}
//				System.err.println(pos);
				doMove(pos);
//				System.err.println(Arrays.toString(a));
				pos = (pos + k - 1) % n;
			}
		}
		if (deferCnt != 0) {
			throw new AssertionError();
		}
	}

	static int scanInt() throws IOException {
		return parseInt(scanString());
	}

	static long scanLong() throws IOException {
		return parseLong(scanString());
	}

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

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

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


import static java.lang.Integer.parseInt;
import static java.lang.Long.parseLong;
import static java.lang.System.exit;
import static java.util.Arrays.fill;

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

public class G {

	interface IntComparator {
		public int compare(int o1, int o2);
	}

	static void sort(int a[], int n, IntComparator cmp) {
		if (n == 0) {
			return;
		}
		for (int i = 1; i < n; i++) {
			int j = i;
			int ca = a[i];
			do {
				int nj = (j - 1) >> 1;
				int na = a[nj];
				if (cmp.compare(na, ca) >= 0) {
					break;
				}
				a[j] = na;
				j = nj;
			} while (j != 0);
			a[j] = ca;
		}
		int ca = a[0];
		for (int i = n - 1; i > 0; i--) {
			int j = 0;
			while ((j << 1) + 2 + Integer.MIN_VALUE < i + Integer.MIN_VALUE) {
				j <<= 1;
				j += (cmp.compare(a[j + 1], a[j + 2]) < 0) ? 2 : 1;
			}
			if ((j << 1) + 2 == i) {
				j = (j << 1) + 1;
			}
			int na = a[i];
			a[i] = ca;
			ca = na;
			while (j != 0 && cmp.compare(a[j], ca) < 0) {
				j = (j - 1) >> 1;
			}
			while (j != 0) {
				na = a[j];
				a[j] = ca;
				ca = na;
				j = (j - 1) >> 1;
			}
		}
		a[0] = ca;
	}

	static int n, k, a[], sum, move[], moveOffset, defer[], deferCnt, derefFirst[];

	static void doMove(int pos) {
		if (a[pos] < (move[(pos + 1) % n] - moveOffset) || a[(pos + k - 1) % n] < -(move[(pos + k - 1) % n] - moveOffset)) {
			if (deferCnt == 0) {
				derefFirst = new int[k - 1];
				for (int i = 0; i < k - 1; i++) {
					derefFirst[i] = move[(pos + i + 1) % n] - moveOffset;
					move[(pos + i + 1) % n] = moveOffset;
				}
			}
			defer[deferCnt++] = pos;
			return;
		}
		for (int i = 0; i < k - 1; i++) {
			int m = move[(pos + i + 1) % n] - moveOffset;
			a[(pos + i) % n] -= m;
			a[(pos + i + 1) % n] += m;
			move[(pos + i + 1) % n] = moveOffset;
		}
		out.print(pos + 1);
		for (int i = 0; i < k; i++) {
			out.print(" " + a[(pos + i) % n]);
		}
		out.println();
		if (deferCnt > 0) {
			if (--deferCnt == 0) {
				pos = defer[0];
				for (int i = 0; i < k - 1; i++) {
					int m = derefFirst[i];
					a[(pos + i) % n] -= m;
					a[(pos + i + 1) % n] += m;
				}
				out.print(pos + 1);
				for (int i = 0; i < k; i++) {
					out.print(" " + a[(pos + i) % n]);
				}
				out.println();
			} else {
				doMove(defer[deferCnt]);
			}
		}
	}

	static void solve() throws Exception {
		n = scanInt();
		k = scanInt();
		a = new int[n];
		sum = 0;
		for (int i = 0; i < n; i++) {
			sum += a[i] = scanInt();
		}
		sum /= n;
		move = new int[n];
		int idx[] = new int[n];
		for (int i = 0; i < n - 1; i++) {
			move[i + 1] = move[i] + a[i] - sum;
			idx[i] = i;
		}
		idx[n - 1] = n - 1;
		sort(idx, n, new IntComparator() {
			public int compare(int o1, int o2) {
				return move[o1] != move[o2] ? move[o1] - move[o2] : o1 - o2;
			}
		});
		int ans = (n + k - 2) / (k - 1), ansStart = -1;
		int maxChain[] = new int[n], curNext[] = new int[k - 1];
		fill(curNext, -1);
		for (int i = 0, j; i < n; i = j) {
			for (j = i + 1; j < n && move[idx[j]] == move[idx[i]]; j++) { }
			for (int ii = j - 1; ii >= i; ii--) {
				int ci = idx[ii], ni = curNext[(ci + 1) % (k - 1)];
//				System.err.println(ci + " " + ni);
				maxChain[ci] = ni < 0 ? 1 : 1 + maxChain[ni];
				int cans = (n - maxChain[ci] + k - 2) / (k - 1);
				if (cans < ans) {
					ans = cans;
					ansStart = ci;
				}
				curNext[ci % (k - 1)] = ci;
			}
			for (int ii = i; ii < j; ii++) {
				curNext[idx[ii] % (k - 1)] = -1;
			}
		}
//		System.err.println(Arrays.toString(maxChain));
		out.println(ans);
		defer = new int[n];
		deferCnt = 0;
//		System.err.println(ans + " " + ansStart + " " + sum);
		if (ansStart < 0) {
			moveOffset = 0;
			for (int i = 0; i < ans; i++) {
				doMove(i * (k - 1));
			}
		} else {
			moveOffset = move[ansStart];
//			System.err.println(Arrays.toString(move) + " " + moveOffset);
			for (int i = 0, pos = ansStart; i < ans; i++) {
				while (move[(pos + 1) % n] == moveOffset) {
					pos = (pos + 1) % n;
				}
//				System.err.println(pos);
				doMove(pos);
//				System.err.println(Arrays.toString(a));
				pos = (pos + k - 1) % n;
			}
		}
		if (deferCnt != 0) {
			throw new AssertionError();
		}
	}

	static int scanInt() throws IOException {
		return parseInt(scanString());
	}

	static long scanLong() throws IOException {
		return parseLong(scanString());
	}

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

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

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


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {

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

        String[] strings = new String[]{"buffy", "the", "vampire", "slayer"};
        String in = br.readLine();
        boolean found = false;
        for (String s : strings) {
            if (s.length() == in.length()) {
                found = true;
                for (int i = 0; i < s.length(); i++) {
                    System.out.print((char) ((in.charAt(i) + s.charAt(i) - 'a' - 'a') % (26) + 'a'));
                }
            }
        }
        if (!found) {
            System.out.println("none");
        }

        br.close();
    }
}


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

import static java.lang.Math.random;

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

    int MOD = (int) 1e9 + 7;

    void solve() {
        int n = in.nextInt();
        int[] a = new int[n];
        for (int i = 0; i < n; i++) a[i] = in.nextInt();

        int[][] c = new int[n + 1][n + 1];
        for (int i = 0; i <= n; i++) {
            c[i][0] = 1;
            for (int j = 1; j <= i; j++) {
                c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % MOD;
            }
        }

        int[] fac = new int[n + 1];
        fac[0] = 1;
        for (int i = 1; i <= n; i++) fac[i] = (int) ((long) i * fac[i - 1] % MOD);

        for (int i = 0; i < n; i++) a[i] = removeSqures(a[i]);

        sort(a);

        long[] ways = new long[]{1};
        for (int i = 0; i < n; ) {
            int j = i + 1;
            while (j < n && a[j] == a[i]) j++;
            int m = j - i;

            long[] nways = new long[j + 1];
            for (int x = 0; x < ways.length; x++) {
                long w = ways[x];
                for (int y = 1; y <= m; y++) {
                    for (int z = 0; z <= x && z <= y; z++) {
                        nways[x - z + (m - y)] = (nways[x - z + (m - y)] + w * c[m - 1][y - 1] % MOD * c[x][z] % MOD * c[i + 1 - x][y - z] % MOD * fac[m] % MOD) % MOD;
                    }
                }
            }

            ways = nways;
            i = j;
        }

        out.println(ways[0]);
    }

    void sort(int[] a) {
        int n = a.length;
        for (int i = 0; i < n; i++) {
            int j = (int) (i + random() * (n - i));
            int tmp = a[i];
            a[i] = a[j];
            a[j] = tmp;
        }
        Arrays.sort(a);
    }

    int removeSqures(int x) {
        for (int i = 2; i * i <= x; i++) {
            while (x % (i * i) == 0) x /= i * i;
        }
        return x;
    }

    public static void main(String[] args) {
        in = new FastScanner(new BufferedReader(new InputStreamReader(System.in)));
        out = new PrintWriter(System.out);
        new OnTheBench().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 sun.security.util.Length;

import java.lang.reflect.Array;
import java.math.BigInteger;
import java.util.*;

public class E {

    public static boolean isSquare(int a, int b) {
        long mult = ((long)a) * b;
        long sqrt = Math.round(Math.sqrt(mult));
        return sqrt * sqrt == mult;
    }

    public static long[] getFacts(int n) {
        long[] f = new long[n + 1];
        f[0] = 1;

        for (int i = 1; i <= n; ++i) {
            f[i] = (f[i - 1] * i) % 1000000007;
        }
        return f;
    }

    public static long[][] getC(int n) {
        long[][] c = new long[n + 1][n + 1];

        for (int i = 0; i <= n; ++i) {
            for (int j = 0; j <= i; j++) {
                if (i == 0 || j == 0) {
                    c[i][j] = 1;
                    continue;
                }

                c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % 1000000007;
            }
        }

        return c;
    }

    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        int[] a = new int[n];
        for (int i = 0; i < n; ++i) {
            a[i] = scan.nextInt();
        }

        int[] aGroup = new int[n + 1];
        int[] groups = new int[n + 1];
        int groupsCnt = 0;
        for (int i = 0; i < n; ++i) {
            int group = groupsCnt;

            for (int j = 0; j < i; ++j) {
                if (isSquare(a[i], a[j])) {
                    group = aGroup[j];
                    break;
                }
            }

            aGroup[i] = group;
            groups[group] = groups[group] + 1;
            groupsCnt = Math.max(groupsCnt, group + 1);
        }

        long[] fact = getFacts(n);
        long[][] c = getC(n);

        long[] f = new long[n];
        f[0] = 1;

        int total = 0;
        for (int i = 0; i < groupsCnt; ++i) {
            //System.out.println(groups[i]);

            long[] fNew = new long[n];

            int size = groups[i];

            for (int j = 0; j <= total; ++j) {
                if (f[j] == 0)
                    continue;

                for (int s = 1; s <= Math.min(size, total + 1); ++s) {
                    for (int d = 0; d <= Math.min(j, s); ++d) {
                        long mult = (fact[size] * c[size - 1][s - 1]) % 1000000007;
                        mult = (mult * c[j][d]) % 1000000007;
                        mult = (mult * c[total - j + 1][s - d]) % 1000000007;

                        fNew[j - d + size - s] = ( fNew[j - d + size - s] + f[j] * mult) % 1000000007;
                    }
                }
            }

            total += (groups[i]);

            //System.out.println(Arrays.toString(Arrays.copyOf(fNew, n)));
            f = fNew;
        }

        System.out.println(f[0]);
    }
}


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

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

    static class TaskE {
        int[] smallestDivisor;

        TaskE.Factorization factorize(int x) {
            int cnt = 0;
            int tmp = x;
            while (tmp > 1) {
                int cur = smallestDivisor[tmp];
                while (tmp % cur == 0) {
                    tmp /= cur;
                }
                ++cnt;
            }
            TaskE.Factorization f = new TaskE.Factorization(cnt);
            tmp = x;
            cnt = 0;
            while (tmp > 1) {
                int cur = smallestDivisor[tmp];
                f.p[cnt] = cur;
                while (tmp % cur == 0) {
                    tmp /= cur;
                    ++f.k[cnt];
                }
                if (f.k[cnt] == 0) throw new RuntimeException();
                ++cnt;
            }
            return f;
        }

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            int n = in.nextInt();
            int[] a = new int[n];
            for (int i = 0; i < n; ++i) a[i] = in.nextInt();
            int maxa = 2;
            for (int x : a) maxa = Math.max(maxa, x);
            ++maxa;

            TaskE.Factorization[] fs = factorizeAll(n, a, maxa);

            long[] bCounts = buildB(n, maxa, fs);

            long bTotal = 0;
            long bSize = 0;
            for (int i = 0; i < bCounts.length; ++i) {
                bTotal += i * bCounts[i];
                bSize += bCounts[i];
            }

            long position = ((bSize * (bSize + 1) / 2) - 1) / 2;

            long left = -1;
            long right = bTotal;
            while (right - left > 1) {
                long middle = (left + right) / 2;
                if (howManyLessOrEqual(bCounts, middle) <= position) {
                    left = middle;
                } else {
                    right = middle;
                }
            }

            out.println(right);
        }

        private long howManyLessOrEqual(long[] bCounts, long bound) {
            long res = 0;
            int right = 0;
            long rightAt = 0;
            long rightTotal = bCounts[0];
            long beforeRight = 0;
            long countBeforeRight = 0;
            long beforeLeft = 0;
            long countBeforeLeft = 0;
            for (int left = 0; left < bCounts.length; ++left) {
                long leftAt = 0;
                long leftTotal = bCounts[left];
                while (leftAt < leftTotal) {
                    while (right < bCounts.length && beforeRight + (rightTotal - rightAt) * right <= beforeLeft + bound) {
                        beforeRight += (rightTotal - rightAt) * right;
                        countBeforeRight += (rightTotal - rightAt);
                        ++right;
                        if (right < bCounts.length) {
                            rightAt = 0;
                            rightTotal = bCounts[right];
                        } else {
                            rightAt = -1;
                            rightTotal = -1;
                        }
                    }
                    if (right == bCounts.length) {
                        long by = leftTotal - leftAt;
                        res += ((countBeforeRight - countBeforeLeft) + (countBeforeRight - countBeforeLeft + by - 1)) * by / 2;
                        leftAt += by;
                        countBeforeLeft += by;
                        beforeLeft += by * left;
                    } else {
                        long maxRight = beforeRight + (rightTotal - rightAt) * right;
                        long by = leftTotal - leftAt;
                        by = Math.min(by, (maxRight - beforeLeft - bound + left - 1) / left);
                        if (by == 0) {
                            throw new RuntimeException();
                        }

                        res += countBeforeRight * by + sumIntPart(left, beforeLeft + bound - beforeRight, right, by);
                        res -= (countBeforeLeft + countBeforeLeft + by - 1) * by / 2;

                        leftAt += by;
                        countBeforeLeft += by;
                        beforeLeft += by * left;
                    }
                }
            }
            return res;
        }

        private long intPartSum(long mult, long modulo, long cnt, long add) {
            if (cnt == 0)
                return 0;
            if (add >= modulo)
                return intPartSum(mult, modulo, cnt, add % modulo) + cnt * (long) (add / modulo);
            if (add < 0)
                return intPartSum(mult, modulo, cnt, add % modulo + modulo) + cnt * (long) (add / modulo - 1);
            if (mult >= modulo)
                return intPartSum(mult % modulo, modulo, cnt, add) + (mult / modulo) * (long) cnt * (long) (cnt + 1) / 2;
            if (mult == 0) {
                return 0;
            }
            int max = (int) ((mult * (long) cnt + add) / modulo);
            return max * (long) cnt - intPartSum(modulo, mult, max, -add - 1);
        }

        private long sumIntPart(long a, long b, long c, long count) {
            if (count == 0) return 0;
            long got = b / c + intPartSum(a, c, count - 1, b);
        /*long expected = 0;
        for (int i = 0; i < count; ++i) {
            expected += (a * i + b) / c;
        }
        if (got != expected) {
            throw new RuntimeException();
        }*/
            return got;
        }

        private long[] buildB(int n, int maxa, TaskE.Factorization[] fs) {
            long[] bCounts = new long[maxa];
            for (int left = 0; left < n; ++left) {
                TaskE.Factorization f = fs[left];
                int[] primes = f.p;
                int[] pow = f.k.clone();
                int[] decrease = f.nextDecrease.clone();
                int at = left;
                while (at < n) {
                    int prod = 1;
                    for (int i = 0; i < primes.length; ++i) {
                        for (int j = 0; j < pow[i]; ++j) {
                            prod *= primes[i];
                        }
                    }
                    int dest = n;
                    for (int i = 0; i < primes.length; ++i) {
                        dest = Math.min(dest, decrease[i]);
                    }
                    bCounts[prod] += dest - at;
                    at = dest;
                    if (at < n) {
                        TaskE.Factorization cur = fs[at];
                        for (int i = 0; i < primes.length; ++i)
                            if (decrease[i] == at) {
                                int pos = Arrays.binarySearch(cur.p, primes[i]);
                                if (pos >= 0) {
                                    pow[i] = cur.k[pos];
                                    decrease[i] = cur.nextDecrease[pos];
                                } else {
                                    pow[i] = 0;
                                    decrease[i] = n;
                                }
                            }
                    }
                }
            }
            return bCounts;
        }

        private TaskE.Factorization[] factorizeAll(int n, int[] a, int maxa) {
            smallestDivisor = new int[maxa];
            for (int i = 2; i < maxa; ++i) {
                smallestDivisor[i] = i;
            }
            for (int i = 2; i * i < maxa; ++i)
                if (smallestDivisor[i] == i) {
                    for (int j = i * i; j < maxa; j += i) if (smallestDivisor[j] == j) smallestDivisor[j] = i;
                }

            TaskE.Factorization[] fs = new TaskE.Factorization[n];
            for (int i = 0; i < n; ++i) fs[i] = factorize(a[i]);

            int[] stackTop = new int[maxa];
            int[] stackTopPos = new int[maxa];

            Arrays.fill(stackTop, n);
            Arrays.fill(stackTopPos, -1);

            for (int i = n - 1; i >= 0; --i) {
                TaskE.Factorization f = fs[i];
                for (int j = 0; j < f.p.length; ++j) {
                    int what = f.p[j];
                    int deg = f.k[j];
                    if (stackTop[what] != i + 1) {
                        stackTop[what] = i + 1;
                        stackTopPos[what] = -1;
                    }
                    while (stackTopPos[what] >= 0 && fs[stackTop[what]].k[stackTopPos[what]] >= deg) {
                        int next = fs[stackTop[what]].nextInStackIndex[stackTopPos[what]];
                        int nextPos = fs[stackTop[what]].nextInStackPos[stackTopPos[what]];
                        stackTop[what] = next;
                        stackTopPos[what] = nextPos;
                    }
                    f.nextDecrease[j] = stackTop[what];
                    f.nextInStackIndex[j] = stackTop[what];
                    f.nextInStackPos[j] = stackTopPos[what];
                    stackTop[what] = i;
                    stackTopPos[what] = j;
                }
            }
            return fs;
        }

        static class Factorization {
            int[] p;
            int[] k;
            int[] nextDecrease;
            int[] nextInStackIndex;
            int[] nextInStackPos;

            public Factorization(int len) {
                p = new int[len];
                k = new int[len];
                nextDecrease = new int[len];
                nextInStackIndex = new int[len];
                nextInStackPos = new int[len];
            }

        }

    }

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

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

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

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

    }
}


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

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

    static class TaskE {
        int[] smallestDivisor;

        TaskE.Factorization factorize(int x) {
            int cnt = 0;
            int tmp = x;
            while (tmp > 1) {
                int cur = smallestDivisor[tmp];
                while (tmp % cur == 0) {
                    tmp /= cur;
                }
                ++cnt;
            }
            TaskE.Factorization f = new TaskE.Factorization(cnt);
            tmp = x;
            cnt = 0;
            while (tmp > 1) {
                int cur = smallestDivisor[tmp];
                f.p[cnt] = cur;
                while (tmp % cur == 0) {
                    tmp /= cur;
                    ++f.k[cnt];
                }
                if (f.k[cnt] == 0) throw new RuntimeException();
                ++cnt;
            }
            return f;
        }

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            int n = in.nextInt();
            int[] a = new int[n];
            for (int i = 0; i < n; ++i) a[i] = in.nextInt();
            int maxa = 2;
            for (int x : a) maxa = Math.max(maxa, x);
            ++maxa;

            TaskE.Factorization[] fs = factorizeAll(n, a, maxa);

            long[] bCounts = buildB(n, maxa, fs);

            long bTotal = 0;
            long bSize = 0;
            for (int i = 0; i < bCounts.length; ++i) {
                bTotal += i * bCounts[i];
                bSize += bCounts[i];
            }

            long position = ((bSize * (bSize + 1) / 2) - 1) / 2;

            long left = -1;
            long right = bTotal;
            while (right - left > 1) {
                long middle = (left + right) / 2;
                if (howManyLessOrEqual(bCounts, middle) <= position) {
                    left = middle;
                } else {
                    right = middle;
                }
            }

            out.println(right);
        }

        private long howManyLessOrEqual(long[] bCounts, long bound) {
            long res = 0;
            int right = 0;
            long rightAt = 0;
            long rightTotal = bCounts[0];
            long beforeRight = 0;
            long countBeforeRight = 0;
            long beforeLeft = 0;
            long countBeforeLeft = 0;
            for (int left = 0; left < bCounts.length; ++left) {
                long leftAt = 0;
                long leftTotal = bCounts[left];
                while (leftAt < leftTotal) {
                    while (right < bCounts.length && beforeRight + (rightTotal - rightAt) * right <= beforeLeft + bound) {
                        beforeRight += (rightTotal - rightAt) * right;
                        countBeforeRight += (rightTotal - rightAt);
                        ++right;
                        if (right < bCounts.length) {
                            rightAt = 0;
                            rightTotal = bCounts[right];
                        } else {
                            rightAt = -1;
                            rightTotal = -1;
                        }
                    }
                    if (right == bCounts.length) {
                        long by = leftTotal - leftAt;
                        res += ((countBeforeRight - countBeforeLeft) + (countBeforeRight - countBeforeLeft - by + 1)) * by / 2;
                        leftAt += by;
                        countBeforeLeft += by;
                        beforeLeft += by * left;
                    } else {
                        long maxRight = beforeRight + (rightTotal - rightAt) * right;
                        long by = leftTotal - leftAt;
                        by = Math.min(by, (maxRight - beforeLeft - bound + left - 1) / left);
                        if (by == 0) {
                            throw new RuntimeException();
                        }

                        res += countBeforeRight * by + sumIntPart(left, beforeLeft + bound - beforeRight, right, by);
                        res -= (countBeforeLeft + countBeforeLeft + by - 1) * by / 2;

                        leftAt += by;
                        countBeforeLeft += by;
                        beforeLeft += by * left;
                    }
                }
            }
            return res;
        }

        private long intPartSum(long mult, long modulo, long cnt, long add) {
            if (cnt == 0)
                return 0;
            if (add >= modulo)
                return intPartSum(mult, modulo, cnt, add % modulo) + cnt * (long) (add / modulo);
            if (add < 0)
                return intPartSum(mult, modulo, cnt, add % modulo + modulo) + cnt * (long) (add / modulo - 1);
            if (mult >= modulo)
                return intPartSum(mult % modulo, modulo, cnt, add) + (mult / modulo) * (long) cnt * (long) (cnt + 1) / 2;
            if (mult == 0) {
                return 0;
            }
            int max = (int) ((mult * (long) cnt + add) / modulo);
            return max * (long) cnt - intPartSum(modulo, mult, max, -add - 1);
        }

        private long sumIntPart(long a, long b, long c, long count) {
            if (count == 0) return 0;
            long got = b / c + intPartSum(a, c, count - 1, b);
        /*long expected = 0;
        for (int i = 0; i < count; ++i) {
            expected += (a * i + b) / c;
        }
        if (got != expected) {
            throw new RuntimeException();
        }*/
            return got;
        }

        private long[] buildB(int n, int maxa, TaskE.Factorization[] fs) {
            long[] bCounts = new long[maxa];
            for (int left = 0; left < n; ++left) {
                TaskE.Factorization f = fs[left];
                int[] primes = f.p;
                int[] pow = f.k.clone();
                int[] decrease = f.nextDecrease.clone();
                int at = left;
                while (at < n) {
                    int prod = 1;
                    for (int i = 0; i < primes.length; ++i) {
                        for (int j = 0; j < pow[i]; ++j) {
                            prod *= primes[i];
                        }
                    }
                    int dest = n;
                    for (int i = 0; i < primes.length; ++i) {
                        dest = Math.min(dest, decrease[i]);
                    }
                    bCounts[prod] += dest - at;
                    at = dest;
                    if (at < n) {
                        TaskE.Factorization cur = fs[at];
                        for (int i = 0; i < primes.length; ++i)
                            if (decrease[i] == at) {
                                int pos = Arrays.binarySearch(cur.p, primes[i]);
                                if (pos >= 0) {
                                    pow[i] = cur.k[pos];
                                    decrease[i] = cur.nextDecrease[pos];
                                } else {
                                    pow[i] = 0;
                                    decrease[i] = n;
                                }
                            }
                    }
                }
            }
            return bCounts;
        }

        private TaskE.Factorization[] factorizeAll(int n, int[] a, int maxa) {
            smallestDivisor = new int[maxa];
            for (int i = 2; i < maxa; ++i) {
                smallestDivisor[i] = i;
            }
            for (int i = 2; i * i < maxa; ++i)
                if (smallestDivisor[i] == i) {
                    for (int j = i * i; j < maxa; j += i) if (smallestDivisor[j] == j) smallestDivisor[j] = i;
                }

            TaskE.Factorization[] fs = new TaskE.Factorization[n];
            for (int i = 0; i < n; ++i) fs[i] = factorize(a[i]);

            int[] stackTop = new int[maxa];
            int[] stackTopPos = new int[maxa];

            Arrays.fill(stackTop, n);
            Arrays.fill(stackTopPos, -1);

            for (int i = n - 1; i >= 0; --i) {
                TaskE.Factorization f = fs[i];
                for (int j = 0; j < f.p.length; ++j) {
                    int what = f.p[j];
                    int deg = f.k[j];
                    if (stackTop[what] != i + 1) {
                        stackTop[what] = i + 1;
                        stackTopPos[what] = -1;
                    }
                    while (stackTopPos[what] >= 0 && fs[stackTop[what]].k[stackTopPos[what]] >= deg) {
                        int next = fs[stackTop[what]].nextInStackIndex[stackTopPos[what]];
                        int nextPos = fs[stackTop[what]].nextInStackPos[stackTopPos[what]];
                        stackTop[what] = next;
                        stackTopPos[what] = nextPos;
                    }
                    f.nextDecrease[j] = stackTop[what];
                    f.nextInStackIndex[j] = stackTop[what];
                    f.nextInStackPos[j] = stackTopPos[what];
                    stackTop[what] = i;
                    stackTopPos[what] = j;
                }
            }
            return fs;
        }

        static class Factorization {
            int[] p;
            int[] k;
            int[] nextDecrease;
            int[] nextInStackIndex;
            int[] nextInStackPos;

            public Factorization(int len) {
                p = new int[len];
                k = new int[len];
                nextDecrease = new int[len];
                nextInStackIndex = new int[len];
                nextInStackPos = new int[len];
            }

        }

    }

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

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

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

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

    }
}


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

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

	static final int M = 20;
	void main() {
		int t = sc.nextInt();
		while (t-- > 0) {
			int n = sc.nextInt();
			byte[] sa = sc.next().getBytes();
			byte[] sb = sc.next().getBytes();
			boolean[][] aa = new boolean[M][M];
			for (int i = 0; i < n; i++)
				if (sa[i] != sb[i]) {
					int u = sa[i] - 'a';
					int v = sb[i] - 'a';
					aa[u][v] = true;
				}
			boolean[][] bb = new boolean[M][M];
			for (int i = 0; i < M; i++)
				for (int j = 0; j < M; j++)
					bb[i][j] = aa[i][j];
			for (int k = 0; k < M; k++)
				for (int i = 0; i < M; i++)
					for (int j = 0; j < M; j++)
						bb[i][j] = bb[i][j] || bb[i][k] && bb[k][j];
			int[] cc = new int[M]; Arrays.fill(cc, -1);
			int ans = 0;
			for (int i = 0; i < M; i++)
				if (bb[i][i]) {
					if (cc[i] == -1)
						for (int j = i; j < M; j++)
							if (cc[j] == -1 && bb[j][j] && bb[i][j] && bb[j][i]) {
								cc[j] = i;
								ans++;
							}
				} else
					cc[i] = i;
			boolean[][] aa_ = new boolean[M][M];
			boolean[][] bb_ = new boolean[M][M];
			for (int i = 0; i < M; i++)
				for (int j = 0; j < M; j++) {
					int i_ = cc[i], j_ = cc[j];
					if (i_ != j_) {
						if (aa[i][j])
							aa_[i_][j_] = true;
						if (bb[i][j])
							bb_[i_][j_] = true;
					}
				}
			boolean[][] ab = new boolean[M][M];
			for (int i = 0; i < M; i++)
				for (int j = 0; j < M; j++)
					for (int k = 0; k < M; k++)
						if (aa_[i][k] && bb_[k][j]) {
							ab[i][j] = true;
							break;
						}
			for (int i = 0; i < M; i++)
				for (int j = 0; j < M; j++)
					if (i != j && aa_[i][j] && !ab[i][j])
						ans++;
			println(ans);
		}
	}
}


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

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

	static final int M = 20;
	void main() {
		int t = sc.nextInt();
		while (t-- > 0) {
			int n = sc.nextInt();
			byte[] sa = sc.next().getBytes();
			byte[] sb = sc.next().getBytes();
			boolean[][] aa = new boolean[M][M];
			for (int i = 0; i < n; i++)
				if (sa[i] != sb[i]) {
					int u = sa[i] - 'a';
					int v = sb[i] - 'a';
					aa[u][v] = true;
				}
			boolean[][] bb = new boolean[M][M];
			for (int i = 0; i < M; i++)
				for (int j = 0; j < M; j++)
					bb[i][j] = aa[i][j];
			for (int k = 0; k < M; k++)
				for (int i = 0; i < M; i++)
					for (int j = 0; j < M; j++)
						bb[i][j] = bb[i][j] || bb[i][k] && bb[k][j];
			int[] cc = new int[M]; Arrays.fill(cc, -1);
			int ans = 0;
			for (int i = 0; i < M; i++)
				if (bb[i][i]) {
					if (cc[i] == -1)
						for (int j = i; j < M; j++)
							if (bb[i][j] && bb[j][j]) {
								cc[j] = i;
								ans++;
							}
				} else
					cc[i] = i;
			boolean[][] aa_ = new boolean[M][M];
			boolean[][] bb_ = new boolean[M][M];
			for (int i = 0; i < M; i++)
				for (int j = 0; j < M; j++) {
					int i_ = cc[i], j_ = cc[j];
					if (i_ != j_) {
						if (aa[i][j])
							aa_[i_][j_] = true;
						if (bb[i][j])
							bb_[i_][j_] = true;
					}
				}
			boolean[][] ab = new boolean[M][M];
			for (int i = 0; i < M; i++)
				for (int j = 0; j < M; j++)
					for (int k = 0; k < M; k++)
						if (aa_[i][k] && bb_[k][j]) {
							ab[i][j] = true;
							break;
						}
			for (int i = 0; i < M; i++)
				for (int j = 0; j < M; j++)
					if (i != j && aa_[i][j] && !ab[i][j])
						ans++;
			println(ans);
		}
	}
}


import java.util.Scanner;

// https://codeforces.com/contest/1384/problem/C
public class C {
	public static final Scanner INPUT = new Scanner(System.in);

	public static void main(String[] args) {
		int t = Integer.parseInt(INPUT.nextLine());
		while (t > 0) {
			t--;
			int n = Integer.parseInt(INPUT.nextLine());
			String a = INPUT.nextLine().trim();
			String b = INPUT.nextLine().trim();
			// System.out.println("n = " + n);
			// System.out.println("a = " + a);
			// System.out.println("b = " + b);
			int[][] c = trans2matrix(a, b, n);
			while (reduce(c)) {
			}
			System.out.println(counter(c));
		}
	}

	private static final int N_SIZE = 20;

	private static boolean reduce(int[][] c) {
		if (c == null) {
			return false;
		}
		boolean canReduce = false;
		for (int i = 0; i < N_SIZE; i++) {
			int last = -1;
			for (int j = i + 1; j < N_SIZE; j++) {
				if (c[i][j] > 0) {
					if (last == -1) {
						last = j;
					} else {
						c[i][last] += c[i][j];
						c[last][j] += c[i][j];
						c[i][j] = 0;
						canReduce = true;
					}
				}
			}
		}
		return canReduce;
	}

	private static int counter(int[][] c) {
		if (c == null) {
			return -1;
		}
		int counter = 0;
		for (int i = 0; i < N_SIZE; i++) {
			for (int j = i + 1; j < N_SIZE; j++) {
				if (c[i][j] > 0) {
					counter++;
				}
			}
		}
		return counter;
	}

	private static int[][] trans2matrix(String a, String b, int n) {
		if (a == null || b == null) {
			return null;
		}
		if ((a.length() != n) || (b.length() != n)) {
			return null;
		}
		int[][] c = new int[N_SIZE][N_SIZE];
		for (int id = 0; id < n; id++) {
			int cA = a.charAt(id) - 'a';
			int cB = b.charAt(id) - 'a';
			if (cA > cB) {
				return null;
			}
			if (cA < cB) {
				c[cA][cB]++;
			}
		}
		return c;
	}
}
/*
 * 5 3 aab bcc 4 cabc abcb 3 abc tsr 4 aabd cccd 5 abcbd bcdda
 */


import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

// https://codeforces.com/contest/1384/problem/E
public class E {
	public static final Scanner IN = new Scanner(System.in);
	public static final int N_SIZE = 20;
	public static final int NN_SIZE = N_SIZE * 2;
	public static int[][] MC = new int[N_SIZE][N_SIZE];
	public static int[][] MMC = new int[NN_SIZE][NN_SIZE];
	public static int[] degs = new int[N_SIZE];
	public static int[] ddegs = new int[NN_SIZE];
	public static int[] ffas = new int[NN_SIZE];
	// coding continue

	public static void main(String[] args) {
		int nTest = Integer.parseInt(IN.nextLine());

		while (nTest > 0) {
			nTest--;
			int n = Integer.parseInt(IN.nextLine());
			String a = IN.nextLine().trim();
			String b = IN.nextLine().trim();
			trans2matrix(a, b, n);
			int solution = NN_SIZE;
			for (int state = 0; state < (1 << N_SIZE); state++) {
				solution = Math.min(solution, cal(state));
			}
			System.out.println(solution);
		}
	}

	private static int cal(int state) {
		doubleMatrix(state);
		for (int id = 0; id < NN_SIZE; id++) {
			ffas[id] = id;
		}
		int nComponent = NN_SIZE;
		Queue<Integer> queue = new LinkedList<Integer>();
		for (int id = 0; id < NN_SIZE; id++) {
			if (ddegs[id] == 0) {
				queue.add(id);
			}
		}
		while (queue.size() > 0) {
			int u = queue.poll();
			for (int v = 0; v < NN_SIZE; v++) {
				if (MMC[u][v] > 0) {
					ddegs[v] -= MMC[u][v];
					if (ddegs[v] == 0) {
						queue.add(v);
					}
					int faU = findFa(ffas, u);
					int faV = findFa(ffas, v);
					if (faU != faV) {
						ffas[faV] = faU;
						nComponent--;
					}
				}
			}
		}
		for (int id = 0; id < NN_SIZE; id++) {
			if (ddegs[id] > 0) {
				return NN_SIZE;
			}
		}
		return NN_SIZE - nComponent;
	}

	private static int findFa(int[] fas, int u) {
		if (fas[u] == u) {
			return u;
		}
		fas[u] = findFa(fas, fas[u]);
		return fas[u];
	}

	private static void doubleMatrix(int state) {
		for (int idi = 0; idi < NN_SIZE; idi++) {
			ddegs[idi] = 0;
			for (int idj = 0; idj < NN_SIZE; idj++) {
				MMC[idi][idj] = 0;
			}
		}
		for (int idi = 0; idi < N_SIZE; idi++) {
			for (int idj = 0; idj < N_SIZE; idj++) {
				if (MC[idi][idj] > 0) {
					if ((state & (1 << idj)) > 0) {
						MMC[idi][idj + N_SIZE] = MC[idi][idj];
						ddegs[idj + N_SIZE] += MC[idi][idj];
					} else {
						MMC[idi][idj] = MC[idi][idj];
						ddegs[idj] += MC[idi][idj];
					}
				}
			}
		}
	}

	private static void trans2matrix(String a, String b, int n) {
		for (int idi = 0; idi < N_SIZE; idi++) {
			degs[idi] = 0;
			for (int idj = 0; idj < N_SIZE; idj++) {
				MC[idi][idj] = 0;
			}
		}
		for (int id = 0; id < n; id++) {
			int valueA = a.charAt(id) - 'a';
			int valueB = b.charAt(id) - 'a';
			if (valueA != valueB) {
				MC[valueA][valueB]++;
				degs[valueA]++;
				degs[valueB]++;
			}
		}
	}
}


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

public class D {

	static final int P = 1_000_000_007;

	void submit() {
		int n = nextInt();
		int[] dp = new int[n + 2];
		dp[0] = 1;
		for (int k = 1; k <= n; k++) {
			int[] nxt = new int[n + 1];
			int need = n + 1 - k;
			for (int i = 0; i <= need + 1; i++) {
				for (int j = 0; i + j - 1 <= need; j++) {
					int prod = (int) ((long) dp[i] * dp[j] % P);

					if (i + j <= need) {
						nxt[i + j] += prod;
						if (nxt[i + j] >= P) {
							nxt[i + j] -= P;
						}
						nxt[i + j] += (int) (2L * prod * (i + j) % P);
						if (nxt[i + j] >= P) {
							nxt[i + j] -= P;
						}

						if (i + j + 1 <= need) {
							nxt[i + j + 1] += prod;
							if (nxt[i + j + 1] >= P) {
								nxt[i + j + 1] -= P;
							}
						}
					}

					if (i + j > 0) {
						int mult = (i + j) * (i + j) - i - j;
						nxt[i + j - 1] += (int) ((long)mult * prod % P);
						if (nxt[i + j - 1] >= P) {
							nxt[i + j - 1] -= P;
						}
					}
				}
			}
			dp = nxt;
//			System.err.println(Arrays.toString(dp));
		}

		out.println(dp[1]);
	}

	void preCalc() {

	}

	void stress() {

	}

	D() throws IOException {
		br = new BufferedReader(new InputStreamReader(System.in));
		out = new PrintWriter(System.out);
		preCalc();
		submit();
		// stress();
		// test();
		out.close();
	}

	static final Random rng = new Random();

	static int rand(int l, int r) {
		return l + rng.nextInt(r - l + 1);
	}

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

	BufferedReader br;
	PrintWriter out;
	StringTokenizer st;

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

	String nextString() {
		try {
			return br.readLine();
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

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

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

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


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

    static class DSingerHouse {
        public void solve(int testNumber, FastInput in, FastOutput out) {
            int n = in.readInt();
            int m = n + 2;
            long[][] dp = new long[n + 1][m + 1];

            Modular mod = new Modular(1e9 + 7);

            dp[0][0] = 1;
            for (int i = 1; i <= n; i++) {
                for (int j = 0; j <= m; j++) {
                    for (int k = 0; k <= m; k++) {
                        int way = mod.mul(dp[i - 1][j], dp[i - 1][k]);
                        if (j + k <= m) {
                            //not appear
                            int next = j + k;
                            dp[i][next] += way;
                        }
                        if (j + k - 1 <= m && j + k - 1 >= 0) {
                            //appear, and concatenate
                            int next = j + k - 1;
                            int local = mod.mul(way, (j + k) * (j + k - 1));
                            dp[i][next] += local;
                        }
                        if (j + k <= m) {
                            //appear, but only appear on one side
                            int next = j + k;
                            int local = mod.mul(way, 2 * (j + k));
                            dp[i][next] += local;
                        }
                        if (j + k + 1 <= m) {
                            //appear, with new in/out
                            int next = j + k + 1;
                            dp[i][next] += way;
                        }
                    }
                }
                dp[i][0] = 1;
                for (int j = 0; j <= m; j++) {
                    dp[i][j] = mod.valueOf(dp[i][j]);
                }
            }

            //debug.debug("dp", dp);
            int ans = (int) dp[n][1];
            out.println(ans);
        }

    }

    static class Modular {
        int 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(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 mul(long x, long y) {
            return valueOf(x * y);
        }

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

    }

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

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

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

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

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

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

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

        public FastOutput println() {
            cache.append(System.lineSeparator());
            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 FastInput {
        private final InputStream is;
        private byte[] buf = new byte[1 << 13];
        private int bufLen;
        private int bufOffset;
        private int next;

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

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

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

        public int readInt() {
            int sign = 1;

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

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

            return val;
        }

    }
}


import java.io.*;

public class P0424D {

	static final int MOD = 1000000007;

	long[][] binoms;

	public static void main(String[] args) throws IOException {

		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		int K = Integer.parseInt(br.readLine());

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

		for (int k = 0; k <= K; k++) {

			dp[k] = new long[K - k + 2];

			for (int p = 0; p < K - k + 2; p++) {

				if (p == 0) {
					dp[k][p] = 1;
				} else if (k == 0) {
					dp[k][p] = 0;
				} else {

					for (int i = 0; i <= p; i++) {
						dp[k][p] += dp[k - 1][i] * dp[k - 1][p - i];
						dp[k][p] %= MOD;
					}

					for (int i = 0; i <= p - 1; i++) {

						long inc = (dp[k - 1][i + 1] * dp[k - 1][p - i]) % MOD;
						inc *= 2 * (i + 1) * (p - i);
						dp[k][p] += inc % MOD;

						inc = (dp[k - 1][i + 2] * dp[k - 1][p - i - 1]) % MOD;
						inc *= 2 * (i + 2) * (i + 1);
						dp[k][p] += inc % MOD;

						inc = (dp[k - 1][i + 1] * dp[k - 1][p - i - 1]) % MOD;
						inc *= 4 * (i + 1);
						dp[k][p] += inc % MOD;

						dp[k][p] += dp[k - 1][i] * dp[k - 1][p - i - 1];
						dp[k][p] %= MOD;

					}
				}

			}

		}

		System.out.println(dp[K][1]);

	}

}


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

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

    static class TaskD {
        static final long MODULO = (long) (1e9 + 7);

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            int k = in.nextInt();
            long[][] comb = new long[k + 2][k + 2];
            comb[0][0] = 1;
            for (int a = 1; a < comb.length; ++a) {
                comb[a][0] = 1;
                for (int b = 1; b < comb.length; ++b) {
                    comb[a][b] = (comb[a - 1][b] + comb[a - 1][b - 1]) % MODULO;
                }
            }
            long[] p2 = new long[k + 2];
            p2[0] = 1;
            for (int i = 1; i < p2.length; ++i) p2[i] = 2 * p2[i - 1] % MODULO;
            long[][] res = new long[k + 1][k + 2];
            long[] ways = new long[k + 2];

            res[0][0] = 1;
            for (int size = 1; size <= k; ++size) {
                ways[0] = 1;
                for (int numpaths = 1; numpaths <= k + 1; ++numpaths) {
                    ways[numpaths] = 0;
                    for (int left = 0; left <= numpaths; ++left) {
                        ways[numpaths] = (ways[numpaths] + res[size - 1][left] * res[size - 1][numpaths - left] % MODULO * comb[numpaths][left]) % MODULO;
                    }
                }
                res[size][0] = 1;
                for (int numpaths = 1; numpaths <= k + 1; ++numpaths) {
                    long sum = ways[numpaths];
                    for (int joinleft = 0; joinleft <= 1; ++joinleft) {
                        for (int joinright = 0; joinright <= 1; ++joinright) {
                            int prevnumpaths = numpaths - 1 + joinleft + joinright;
                            if (prevnumpaths >= 0 && prevnumpaths <= k + 1) {
                                long cur = ways[prevnumpaths];
                            /*if (joinleft > 0) {
                                cur = cur * prevnumpaths % MODULO;
                                --prevnumpaths;
                            }
                            if (joinright > 0) {
                                cur = cur * prevnumpaths % MODULO;
                                --prevnumpaths;
                            }
                            if (joinleft > 0 && joinright > 0) {
                                cur = cur * inv2 % MODULO;
                            }*/
                                sum = (sum + cur * numpaths) % MODULO;
                            }
                        }
                    }
                    res[size][numpaths] = sum % MODULO;
                }
            }
            out.println(res[k][1]);
        }

    }

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

    }
}


//package round791;
import java.io.*;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.InputMismatchException;
import java.util.Queue;

public class F2 {
	InputStream is;
	FastWriter out;
	String INPUT = "";

	void solve()
	{
		int n = ni();
		boolean[][] g = new boolean[10][10];
		for(int m = ni();m > 0;m--){
			int x = ni(), y = ni();
			g[x][y] = g[y][x] = true;
		}
		for(int i = 0;i < 10;i++)g[i][i] = true;

		int[][] njs = new int[1<<9][10];
		for(int j = 0;j < 1<<9;j++) {
			for (int k = 0; k < 10; k++) {
				if (j << ~k >= 0) {
					int nj = j;
					for (int l = 0; l < 10; l++) {
						if (g[k][l]) {
							if (k > l) {
								nj |= 1 << l;
							}
						} else {
							nj &= ~(1 << l);
						}
					}
					njs[j][k] = nj;
				}
			}
		}

		long[] dp = new long[1<<9];
		dp[0] = 1;
		for(int i = 1;i <= n;i++){
			long[] ndp = new long[1<<9];
			for(int j = 0;j < 1<<9;j++){
				for(int k = 0;k < 10;k++){
					if (j << ~k >= 0) {
						int nj = njs[j][k];
						ndp[nj] += dp[j];
						if(ndp[nj] >= mod)ndp[nj] -= mod;
					}
				}
			}
			dp = ndp;
		}
		long ans = sum(dp) % mod;
		out.println(ans);
	}

	public static long sum(long... a){long ret = 0; for(long v : a)ret += v; return ret;}

	public static final int mod = 998244353;
	public static final int G = 3;

	// only 998244353
	public static long[] mul(long[] a, long[] b)
	{
		if(a.length == 0 && b.length == 0)return new long[0];
		if(a.length + b.length >= 300) {
			return Arrays.copyOf(NTTStockham998244353.convolve(a, b), a.length + b.length - 1);
		}else{
			return mulnaive(a, b);
		}
	}

	public static long[] mul(long[] a, long[] b, int lim)
	{
		if(a.length + b.length >= 300) {
			return Arrays.copyOf(NTTStockham998244353.convolve(a, b), lim);
		}else{
			return mulnaive(a, b, lim);
		}
	}

	//	public static final int mod = 1000000007;
	//	public static long[] mul(long[] a, long[] b)
	//	{
	//		if(Math.max(a.length, b.length) >= 3000){
	//			return Arrays.copyOf(NTTCRT.convolve(a, b, 3, mod), a.length+b.length-1);
	//		}else{
	//			return mulnaive(a, b);
	//		}
	//	}

	//	public static long[] mul(long[] a, long[] b, int lim)
	//	{
	//		if(Math.max(a.length, b.length) >= 3000){
	//			return Arrays.copyOf(NTTCRT.convolve(a, b, 3, mod), lim);
	//		}else{
	//			return mulnaive(a, b, lim);
	//		}
	//	}

	public static final long big = (Long.MAX_VALUE/mod/mod-1)*mod*mod;

	public static long[] mulnaive(long[] a, long[] b)
	{
		long[] c = new long[a.length+b.length-1];
		for(int i = 0;i < a.length;i++){
			for(int j = 0;j < b.length;j++){
				c[i+j] += a[i]*b[j];
				if(c[i+j] >= big)c[i+j] -= big;
			}
		}
		for(int i = 0;i < c.length;i++)c[i] %= mod;
		return c;
	}

	public static long[] mulnaive(long[] a, long[] b, int lim)
	{
		long[] c = new long[lim];
		for(int i = 0;i < a.length;i++){
			for(int j = 0;j < b.length && i+j < lim;j++){
				c[i+j] += a[i]*b[j];
				if(c[i+j] >= big)c[i+j] -= big;
			}
		}
		for(int i = 0;i < c.length;i++)c[i] %= mod;
		return c;
	}

	public static class NTTStockham998244353 {
		private static final int P = 998244353, mod = P, G = 3;
		private static long[] wps;

		public static long[] convolve(long[] a, long[] b)
		{
			int m = Math.max(2, Integer.highestOneBit(Math.max(a.length, b.length)-1)<<2);

			wps = new long[m];
			long unit = pow(G, (P-1)/m);
			wps[0] = 1;
			for(int p = 1;p < m;p++) {
				wps[p] = wps[p-1] * unit % mod;
			}

			long[] fa = go(a, m, false);
			long[] fb = a == b ? fa : go(b, m, false);
			for(int i = 0;i < m;i++){
				fa[i] = fa[i]*fb[i] % mod;
			}
			fa = go(fa, m, true);
			for(int i = 1, j = m-1;i < j;i++,j--) {
				long d = fa[i]; fa[i] = fa[j]; fa[j] = d;
			}
			return fa;
		}

		private static void fft(long[] X, long[] Y)
		{
			int s = 1;
			boolean eo = false;
			for(int n = X.length;n >= 4;n /= 2) {
				int m = n/2;
				for(int p = 0;p < m;p++) {
					long wp = wps[s*p];
					long wk = (wp<<32)/P;
					for(int q = 0;q < s;q++) {
						long a = X[q + s*(p+0)];
						long b = X[q + s*(p+m)];
						long ndsts = a + b;
						if(ndsts >= 2*P)ndsts -= 2*P;
						long T = a - b + 2*P;
						long Q = wk*T>>>32;
						Y[q + s*(2*p+0)] = ndsts;
						Y[q + s*(2*p+1)] = wp*T-Q*P&(1L<<32)-1;
					}
				}
				s *= 2;
				eo = !eo;
				long[] D = X; X = Y; Y = D;
			}
			long[] z = eo ? Y : X;
			for(int q = 0;q < s;q++) {
				long a = X[q + 0];
				long b = X[q + s];
				z[q+0] = (a+b) % P;
				z[q+s] = (a-b+2*P) % P;
			}
		}

		//	private static void fft(long[] X, long[] Y)
		//	{
		//		int s = 1;
		//		boolean eo = false;
		//		for(int n = X.length;n >= 4;n /= 2) {
		//			int m = n/2;
		//			for(int p = 0;p < m;p++) {
		//				long wp = wps[s*p];
		//				for(int q = 0;q < s;q++) {
		//					long a = X[q + s*(p+0)];
		//					long b = X[q + s*(p+m)];
		//					Y[q + s*(2*p+0)] = (a+b) % P;
		//					Y[q + s*(2*p+1)] = (a-b+P) * wp % P;
		//				}
		//			}
		//			s *= 2;
		//			eo = !eo;
		//			long[] D = X; X = Y; Y = D;
		//		}
		//		long[] z = eo ? Y : X;
		//		for(int q = 0;q < s;q++) {
		//			long a = X[q + 0];
		//			long b = X[q + s];
		//			z[q+0] = (a+b) % P;
		//			z[q+s] = (a-b+P) % P;
		//		}
		//	}

		private static long[] go(long[] src, int n, boolean inverse)
		{
			long[] dst = Arrays.copyOf(src, n);
			fft(dst, new long[n]);
			if(inverse){
				long in = invl(n);
				for(int i = 0;i < n;i++){
					dst[i] = dst[i] * in % mod;
				}
			}

			return dst;
		}

		private static long pow(long a, long n) {
			//		a %= mod;
			long ret = 1;
			int x = 63 - Long.numberOfLeadingZeros(n);
			for (; x >= 0; x--) {
				ret = ret*ret % mod;
				if (n<<~x<0)ret = ret*a%mod;
			}
			return ret;
		}

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

	public static long C(int n, int r, int mod, int[][] fif) {
		if (n < 0 || r < 0 || r > n) return 0;
		return (long) fif[0][n] * fif[1][r] % mod * fif[1][n - r] % mod;
	}

	public static int[][] enumFIF(int n, int mod) {
		int[] f = new int[n + 1];
		int[] invf = new int[n + 1];
		f[0] = 1;
		for (int i = 1; i <= n; i++) {
			f[i] = (int) ((long) f[i - 1] * i % mod);
		}
		long a = f[n];
		long b = mod;
		long p = 1, q = 0;
		while (b > 0) {
			long c = a / b;
			long d;
			d = a;
			a = b;
			b = d % b;
			d = p;
			p = q;
			q = d - c * q;
		}
		invf[n] = (int) (p < 0 ? p + mod : p);
		for (int i = n - 1; i >= 0; i--) {
			invf[i] = (int) ((long) invf[i + 1] * (i + 1) % mod);
		}
		return new int[][]{f, invf};
	}

	public static class DJSet {
		public int[] upper;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	private long[] nal(int n)
	{
		long[] a = new long[n];
		for(int i = 0;i < n;i++)a[i] = nl();
		return a;
	}

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

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

	private int ni() { return (int)nl(); }

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

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

	public static class FastWriter
	{
		private static final int BUF_SIZE = 1<<13;
		private final byte[] buf = new byte[BUF_SIZE];
		private final OutputStream out;
		private int ptr = 0;

		private FastWriter(){out = null;}

		public FastWriter(OutputStream os)
		{
			this.out = os;
		}

		public FastWriter(String path)
		{
			try {
				this.out = new FileOutputStream(path);
			} catch (FileNotFoundException e) {
				throw new RuntimeException("FastWriter");
			}
		}

		public FastWriter write(byte b)
		{
			buf[ptr++] = b;
			if(ptr == BUF_SIZE)innerflush();
			return this;
		}

		public FastWriter write(char c)
		{
			return write((byte)c);
		}

		public FastWriter write(char[] s)
		{
			for(char c : s){
				buf[ptr++] = (byte)c;
				if(ptr == BUF_SIZE)innerflush();
			}
			return this;
		}

		public FastWriter write(String s)
		{
			s.chars().forEach(c -> {
				buf[ptr++] = (byte)c;
				if(ptr == BUF_SIZE)innerflush();
			});
			return this;
		}

		private static int countDigits(int l) {
			if (l >= 1000000000) return 10;
			if (l >= 100000000) return 9;
			if (l >= 10000000) return 8;
			if (l >= 1000000) return 7;
			if (l >= 100000) return 6;
			if (l >= 10000) return 5;
			if (l >= 1000) return 4;
			if (l >= 100) return 3;
			if (l >= 10) return 2;
			return 1;
		}

		public FastWriter write(int x)
		{
			if(x == Integer.MIN_VALUE){
				return write((long)x);
			}
			if(ptr + 12 >= BUF_SIZE)innerflush();
			if(x < 0){
				write((byte)'-');
				x = -x;
			}
			int d = countDigits(x);
			for(int i = ptr + d - 1;i >= ptr;i--){
				buf[i] = (byte)('0'+x%10);
				x /= 10;
			}
			ptr += d;
			return this;
		}

		private static int countDigits(long l) {
			if (l >= 1000000000000000000L) return 19;
			if (l >= 100000000000000000L) return 18;
			if (l >= 10000000000000000L) return 17;
			if (l >= 1000000000000000L) return 16;
			if (l >= 100000000000000L) return 15;
			if (l >= 10000000000000L) return 14;
			if (l >= 1000000000000L) return 13;
			if (l >= 100000000000L) return 12;
			if (l >= 10000000000L) return 11;
			if (l >= 1000000000L) return 10;
			if (l >= 100000000L) return 9;
			if (l >= 10000000L) return 8;
			if (l >= 1000000L) return 7;
			if (l >= 100000L) return 6;
			if (l >= 10000L) return 5;
			if (l >= 1000L) return 4;
			if (l >= 100L) return 3;
			if (l >= 10L) return 2;
			return 1;
		}

		public FastWriter write(long x)
		{
			if(x == Long.MIN_VALUE){
				return write("" + x);
			}
			if(ptr + 21 >= BUF_SIZE)innerflush();
			if(x < 0){
				write((byte)'-');
				x = -x;
			}
			int d = countDigits(x);
			for(int i = ptr + d - 1;i >= ptr;i--){
				buf[i] = (byte)('0'+x%10);
				x /= 10;
			}
			ptr += d;
			return this;
		}

		public FastWriter write(double x, int precision)
		{
			if(x < 0){
				write('-');
				x = -x;
			}
			x += Math.pow(10, -precision)/2;
			//		if(x < 0){ x = 0; }
			write((long)x).write(".");
			x -= (long)x;
			for(int i = 0;i < precision;i++){
				x *= 10;
				write((char)('0'+(int)x));
				x -= (int)x;
			}
			return this;
		}

		public FastWriter writeln(char c){
			return write(c).writeln();
		}

		public FastWriter writeln(int x){
			return write(x).writeln();
		}

		public FastWriter writeln(long x){
			return write(x).writeln();
		}

		public FastWriter writeln(double x, int precision){
			return write(x, precision).writeln();
		}

		public FastWriter write(int... xs)
		{
			boolean first = true;
			for(int x : xs) {
				if (!first) write(' ');
				first = false;
				write(x);
			}
			return this;
		}

		public FastWriter write(long... xs)
		{
			boolean first = true;
			for(long x : xs) {
				if (!first) write(' ');
				first = false;
				write(x);
			}
			return this;
		}

		public FastWriter writeln()
		{
			return write((byte)'\n');
		}

		public FastWriter writeln(int... xs)
		{
			return write(xs).writeln();
		}

		public FastWriter writeln(long... xs)
		{
			return write(xs).writeln();
		}

		public FastWriter writeln(char[] line)
		{
			return write(line).writeln();
		}

		public FastWriter writeln(char[]... map)
		{
			for(char[] line : map)write(line).writeln();
			return this;
		}

		public FastWriter writeln(String s)
		{
			return write(s).writeln();
		}

		private void innerflush()
		{
			try {
				out.write(buf, 0, ptr);
				ptr = 0;
			} catch (IOException e) {
				throw new RuntimeException("innerflush");
			}
		}

		public void flush()
		{
			innerflush();
			try {
				out.flush();
			} catch (IOException e) {
				throw new RuntimeException("flush");
			}
		}

		public FastWriter print(byte b) { return write(b); }
		public FastWriter print(char c) { return write(c); }
		public FastWriter print(char[] s) { return write(s); }
		public FastWriter print(String s) { return write(s); }
		public FastWriter print(int x) { return write(x); }
		public FastWriter print(long x) { return write(x); }
		public FastWriter print(double x, int precision) { return write(x, precision); }
		public FastWriter println(char c){ return writeln(c); }
		public FastWriter println(int x){ return writeln(x); }
		public FastWriter println(long x){ return writeln(x); }
		public FastWriter println(double x, int precision){ return writeln(x, precision); }
		public FastWriter print(int... xs) { return write(xs); }
		public FastWriter print(long... xs) { return write(xs); }
		public FastWriter println(int... xs) { return writeln(xs); }
		public FastWriter println(long... xs) { return writeln(xs); }
		public FastWriter println(char[] line) { return writeln(line); }
		public FastWriter println(char[]... map) { return writeln(map); }
		public FastWriter println(String s) { return writeln(s); }
		public FastWriter println() { return writeln(); }
	}

	public void trnz(int... o)
	{
		for(int i = 0;i < o.length;i++)if(o[i] != 0)System.out.print(i+":"+o[i]+" ");
		System.out.println();
	}

	// print ids which are 1
	public void trt(long... o)
	{
		Queue<Integer> stands = new ArrayDeque<>();
		for(int i = 0;i < o.length;i++){
			for(long x = o[i];x != 0;x &= x-1)stands.add(i<<6|Long.numberOfTrailingZeros(x));
		}
		System.out.println(stands);
	}

	public void tf(boolean... r)
	{
		for(boolean x : r)System.out.print(x?'#':'.');
		System.out.println();
	}

	public void tf(boolean[]... b)
	{
		for(boolean[] r : b) {
			for(boolean x : r)System.out.print(x?'#':'.');
			System.out.println();
		}
		System.out.println();
	}

	public void tf(long[]... b)
	{
		if(INPUT.length() != 0) {
			for (long[] r : b) {
				for (long x : r) {
					for (int i = 0; i < 64; i++) {
						System.out.print(x << ~i < 0 ? '#' : '.');
					}
				}
				System.out.println();
			}
			System.out.println();
		}
	}

	public void tf(long... b)
	{
		if(INPUT.length() != 0) {
			for (long x : b) {
				for (int i = 0; i < 64; i++) {
					System.out.print(x << ~i < 0 ? '#' : '.');
				}
			}
			System.out.println();
		}
	}

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


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

public class F {

	static IOHandler sc = new IOHandler();

	static int mod = 998244353;

	//static Integer [][]  memo;

	static Map<Integer, Integer> [] memo;

	static int [] ored;
	static int [] clear;

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		solve(0);
	}

	private static void solve(int t) {
		int n = sc.nextInt();
		memo = new Map[1024];

		for (int i = 0; i < memo.length; ++i)
			memo[i] = new HashMap<>();

		boolean [][] digits = new boolean [10][10];

		int m = sc.nextInt();

		int a,b;

		for (int i = 0; i < m; ++i) {
			a = sc.nextInt();
			b = sc.nextInt();

			digits[a][b] = true;
			digits[b][a] = true;
		}

		ored = new int [10];
		clear = new int [10];

		for (int i = 0; i < 10; ++i) {
			for (int j = 0; j < 10; ++j) {
				if (i == j || !digits[i][j]) continue;

				clear[i] = clear[i] | (1 << j);
			}
		}

		for (int i = 0; i < 10; ++i) {
			for (int j = i - 1; j >= 0; --j) {
				if (!digits[i][j]) continue;

				ored[i] = ored[i] | (1 << j);
			}
		}

		System.out.println(solve2(n , 0));
	}

	private static int solve2(int n, int pos) {
		if (n == 0) return 1;
		else if (memo[pos].containsKey(n))
			return memo[pos].get(n);

		int cur;
		int result = 0;

		for (int i = 0; i < 10; ++i) {

			if ( ( pos & (1 << i) ) != 0 ) continue;

			cur = pos;
			cur = cur & clear[i];
			cur = cur | ored[i];

			result += solve2(n - 1 , cur);

			result %= mod;
		}

		memo[pos].put(n, result);
		return result;
	}

	private static class IOHandler {
      BufferedReader br;
      StringTokenizer st;

      public IOHandler() {
         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;
      }

   }

}


//package round791;
import java.io.*;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.InputMismatchException;
import java.util.Queue;

public class F2 {
	InputStream is;
	FastWriter out;
	String INPUT = "";

	void solve()
	{
		int n = ni();
		boolean[][] g = new boolean[10][10];
		for(int m = ni();m > 0;m--){
			int x = ni(), y = ni();
			g[x][y] = g[y][x] = true;
		}
		for(int i = 0;i < 10;i++)g[i][i] = true;

		int[][] njs = new int[1<<10][10];
		for(int j = 0;j < 1<<10;j++) {
			for (int k = 0; k < 10; k++) {
				if (j << ~k >= 0) {
					int nj = j;
					for (int l = 0; l < 10; l++) {
						if (g[k][l]) {
							if (k > l) {
								nj |= 1 << l;
							}
						} else {
							nj &= ~(1 << l);
						}
					}
					njs[j][k] = nj;
				}
			}
		}

		long[] dp = new long[1<<10];
		dp[0] = 1;
		for(int i = 1;i <= n;i++){
			long[] ndp = new long[1<<10];
			for(int j = 0;j < 1<<10;j++){
				for(int k = 0;k < 10;k++){
					if (j << ~k >= 0) {
						int nj = njs[j][k];
						ndp[nj] += dp[j];
						if(ndp[nj] >= mod)ndp[nj] -= mod;
					}
				}
			}
			dp = ndp;
		}
		long ans = sum(dp) % mod;
		out.println(ans);
	}

	public static long sum(long... a){long ret = 0; for(long v : a)ret += v; return ret;}

	public static final int mod = 998244353;
	public static final int G = 3;

	// only 998244353
	public static long[] mul(long[] a, long[] b)
	{
		if(a.length == 0 && b.length == 0)return new long[0];
		if(a.length + b.length >= 300) {
			return Arrays.copyOf(NTTStockham998244353.convolve(a, b), a.length + b.length - 1);
		}else{
			return mulnaive(a, b);
		}
	}

	public static long[] mul(long[] a, long[] b, int lim)
	{
		if(a.length + b.length >= 300) {
			return Arrays.copyOf(NTTStockham998244353.convolve(a, b), lim);
		}else{
			return mulnaive(a, b, lim);
		}
	}

	//	public static final int mod = 1000000007;
	//	public static long[] mul(long[] a, long[] b)
	//	{
	//		if(Math.max(a.length, b.length) >= 3000){
	//			return Arrays.copyOf(NTTCRT.convolve(a, b, 3, mod), a.length+b.length-1);
	//		}else{
	//			return mulnaive(a, b);
	//		}
	//	}

	//	public static long[] mul(long[] a, long[] b, int lim)
	//	{
	//		if(Math.max(a.length, b.length) >= 3000){
	//			return Arrays.copyOf(NTTCRT.convolve(a, b, 3, mod), lim);
	//		}else{
	//			return mulnaive(a, b, lim);
	//		}
	//	}

	public static final long big = (Long.MAX_VALUE/mod/mod-1)*mod*mod;

	public static long[] mulnaive(long[] a, long[] b)
	{
		long[] c = new long[a.length+b.length-1];
		for(int i = 0;i < a.length;i++){
			for(int j = 0;j < b.length;j++){
				c[i+j] += a[i]*b[j];
				if(c[i+j] >= big)c[i+j] -= big;
			}
		}
		for(int i = 0;i < c.length;i++)c[i] %= mod;
		return c;
	}

	public static long[] mulnaive(long[] a, long[] b, int lim)
	{
		long[] c = new long[lim];
		for(int i = 0;i < a.length;i++){
			for(int j = 0;j < b.length && i+j < lim;j++){
				c[i+j] += a[i]*b[j];
				if(c[i+j] >= big)c[i+j] -= big;
			}
		}
		for(int i = 0;i < c.length;i++)c[i] %= mod;
		return c;
	}

	public static class NTTStockham998244353 {
		private static final int P = 998244353, mod = P, G = 3;
		private static long[] wps;

		public static long[] convolve(long[] a, long[] b)
		{
			int m = Math.max(2, Integer.highestOneBit(Math.max(a.length, b.length)-1)<<2);

			wps = new long[m];
			long unit = pow(G, (P-1)/m);
			wps[0] = 1;
			for(int p = 1;p < m;p++) {
				wps[p] = wps[p-1] * unit % mod;
			}

			long[] fa = go(a, m, false);
			long[] fb = a == b ? fa : go(b, m, false);
			for(int i = 0;i < m;i++){
				fa[i] = fa[i]*fb[i] % mod;
			}
			fa = go(fa, m, true);
			for(int i = 1, j = m-1;i < j;i++,j--) {
				long d = fa[i]; fa[i] = fa[j]; fa[j] = d;
			}
			return fa;
		}

		private static void fft(long[] X, long[] Y)
		{
			int s = 1;
			boolean eo = false;
			for(int n = X.length;n >= 4;n /= 2) {
				int m = n/2;
				for(int p = 0;p < m;p++) {
					long wp = wps[s*p];
					long wk = (wp<<32)/P;
					for(int q = 0;q < s;q++) {
						long a = X[q + s*(p+0)];
						long b = X[q + s*(p+m)];
						long ndsts = a + b;
						if(ndsts >= 2*P)ndsts -= 2*P;
						long T = a - b + 2*P;
						long Q = wk*T>>>32;
						Y[q + s*(2*p+0)] = ndsts;
						Y[q + s*(2*p+1)] = wp*T-Q*P&(1L<<32)-1;
					}
				}
				s *= 2;
				eo = !eo;
				long[] D = X; X = Y; Y = D;
			}
			long[] z = eo ? Y : X;
			for(int q = 0;q < s;q++) {
				long a = X[q + 0];
				long b = X[q + s];
				z[q+0] = (a+b) % P;
				z[q+s] = (a-b+2*P) % P;
			}
		}

		//	private static void fft(long[] X, long[] Y)
		//	{
		//		int s = 1;
		//		boolean eo = false;
		//		for(int n = X.length;n >= 4;n /= 2) {
		//			int m = n/2;
		//			for(int p = 0;p < m;p++) {
		//				long wp = wps[s*p];
		//				for(int q = 0;q < s;q++) {
		//					long a = X[q + s*(p+0)];
		//					long b = X[q + s*(p+m)];
		//					Y[q + s*(2*p+0)] = (a+b) % P;
		//					Y[q + s*(2*p+1)] = (a-b+P) * wp % P;
		//				}
		//			}
		//			s *= 2;
		//			eo = !eo;
		//			long[] D = X; X = Y; Y = D;
		//		}
		//		long[] z = eo ? Y : X;
		//		for(int q = 0;q < s;q++) {
		//			long a = X[q + 0];
		//			long b = X[q + s];
		//			z[q+0] = (a+b) % P;
		//			z[q+s] = (a-b+P) % P;
		//		}
		//	}

		private static long[] go(long[] src, int n, boolean inverse)
		{
			long[] dst = Arrays.copyOf(src, n);
			fft(dst, new long[n]);
			if(inverse){
				long in = invl(n);
				for(int i = 0;i < n;i++){
					dst[i] = dst[i] * in % mod;
				}
			}

			return dst;
		}

		private static long pow(long a, long n) {
			//		a %= mod;
			long ret = 1;
			int x = 63 - Long.numberOfLeadingZeros(n);
			for (; x >= 0; x--) {
				ret = ret*ret % mod;
				if (n<<~x<0)ret = ret*a%mod;
			}
			return ret;
		}

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

	public static long C(int n, int r, int mod, int[][] fif) {
		if (n < 0 || r < 0 || r > n) return 0;
		return (long) fif[0][n] * fif[1][r] % mod * fif[1][n - r] % mod;
	}

	public static int[][] enumFIF(int n, int mod) {
		int[] f = new int[n + 1];
		int[] invf = new int[n + 1];
		f[0] = 1;
		for (int i = 1; i <= n; i++) {
			f[i] = (int) ((long) f[i - 1] * i % mod);
		}
		long a = f[n];
		long b = mod;
		long p = 1, q = 0;
		while (b > 0) {
			long c = a / b;
			long d;
			d = a;
			a = b;
			b = d % b;
			d = p;
			p = q;
			q = d - c * q;
		}
		invf[n] = (int) (p < 0 ? p + mod : p);
		for (int i = n - 1; i >= 0; i--) {
			invf[i] = (int) ((long) invf[i + 1] * (i + 1) % mod);
		}
		return new int[][]{f, invf};
	}

	public static class DJSet {
		public int[] upper;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	private long[] nal(int n)
	{
		long[] a = new long[n];
		for(int i = 0;i < n;i++)a[i] = nl();
		return a;
	}

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

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

	private int ni() { return (int)nl(); }

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

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

	public static class FastWriter
	{
		private static final int BUF_SIZE = 1<<13;
		private final byte[] buf = new byte[BUF_SIZE];
		private final OutputStream out;
		private int ptr = 0;

		private FastWriter(){out = null;}

		public FastWriter(OutputStream os)
		{
			this.out = os;
		}

		public FastWriter(String path)
		{
			try {
				this.out = new FileOutputStream(path);
			} catch (FileNotFoundException e) {
				throw new RuntimeException("FastWriter");
			}
		}

		public FastWriter write(byte b)
		{
			buf[ptr++] = b;
			if(ptr == BUF_SIZE)innerflush();
			return this;
		}

		public FastWriter write(char c)
		{
			return write((byte)c);
		}

		public FastWriter write(char[] s)
		{
			for(char c : s){
				buf[ptr++] = (byte)c;
				if(ptr == BUF_SIZE)innerflush();
			}
			return this;
		}

		public FastWriter write(String s)
		{
			s.chars().forEach(c -> {
				buf[ptr++] = (byte)c;
				if(ptr == BUF_SIZE)innerflush();
			});
			return this;
		}

		private static int countDigits(int l) {
			if (l >= 1000000000) return 10;
			if (l >= 100000000) return 9;
			if (l >= 10000000) return 8;
			if (l >= 1000000) return 7;
			if (l >= 100000) return 6;
			if (l >= 10000) return 5;
			if (l >= 1000) return 4;
			if (l >= 100) return 3;
			if (l >= 10) return 2;
			return 1;
		}

		public FastWriter write(int x)
		{
			if(x == Integer.MIN_VALUE){
				return write((long)x);
			}
			if(ptr + 12 >= BUF_SIZE)innerflush();
			if(x < 0){
				write((byte)'-');
				x = -x;
			}
			int d = countDigits(x);
			for(int i = ptr + d - 1;i >= ptr;i--){
				buf[i] = (byte)('0'+x%10);
				x /= 10;
			}
			ptr += d;
			return this;
		}

		private static int countDigits(long l) {
			if (l >= 1000000000000000000L) return 19;
			if (l >= 100000000000000000L) return 18;
			if (l >= 10000000000000000L) return 17;
			if (l >= 1000000000000000L) return 16;
			if (l >= 100000000000000L) return 15;
			if (l >= 10000000000000L) return 14;
			if (l >= 1000000000000L) return 13;
			if (l >= 100000000000L) return 12;
			if (l >= 10000000000L) return 11;
			if (l >= 1000000000L) return 10;
			if (l >= 100000000L) return 9;
			if (l >= 10000000L) return 8;
			if (l >= 1000000L) return 7;
			if (l >= 100000L) return 6;
			if (l >= 10000L) return 5;
			if (l >= 1000L) return 4;
			if (l >= 100L) return 3;
			if (l >= 10L) return 2;
			return 1;
		}

		public FastWriter write(long x)
		{
			if(x == Long.MIN_VALUE){
				return write("" + x);
			}
			if(ptr + 21 >= BUF_SIZE)innerflush();
			if(x < 0){
				write((byte)'-');
				x = -x;
			}
			int d = countDigits(x);
			for(int i = ptr + d - 1;i >= ptr;i--){
				buf[i] = (byte)('0'+x%10);
				x /= 10;
			}
			ptr += d;
			return this;
		}

		public FastWriter write(double x, int precision)
		{
			if(x < 0){
				write('-');
				x = -x;
			}
			x += Math.pow(10, -precision)/2;
			//		if(x < 0){ x = 0; }
			write((long)x).write(".");
			x -= (long)x;
			for(int i = 0;i < precision;i++){
				x *= 10;
				write((char)('0'+(int)x));
				x -= (int)x;
			}
			return this;
		}

		public FastWriter writeln(char c){
			return write(c).writeln();
		}

		public FastWriter writeln(int x){
			return write(x).writeln();
		}

		public FastWriter writeln(long x){
			return write(x).writeln();
		}

		public FastWriter writeln(double x, int precision){
			return write(x, precision).writeln();
		}

		public FastWriter write(int... xs)
		{
			boolean first = true;
			for(int x : xs) {
				if (!first) write(' ');
				first = false;
				write(x);
			}
			return this;
		}

		public FastWriter write(long... xs)
		{
			boolean first = true;
			for(long x : xs) {
				if (!first) write(' ');
				first = false;
				write(x);
			}
			return this;
		}

		public FastWriter writeln()
		{
			return write((byte)'\n');
		}

		public FastWriter writeln(int... xs)
		{
			return write(xs).writeln();
		}

		public FastWriter writeln(long... xs)
		{
			return write(xs).writeln();
		}

		public FastWriter writeln(char[] line)
		{
			return write(line).writeln();
		}

		public FastWriter writeln(char[]... map)
		{
			for(char[] line : map)write(line).writeln();
			return this;
		}

		public FastWriter writeln(String s)
		{
			return write(s).writeln();
		}

		private void innerflush()
		{
			try {
				out.write(buf, 0, ptr);
				ptr = 0;
			} catch (IOException e) {
				throw new RuntimeException("innerflush");
			}
		}

		public void flush()
		{
			innerflush();
			try {
				out.flush();
			} catch (IOException e) {
				throw new RuntimeException("flush");
			}
		}

		public FastWriter print(byte b) { return write(b); }
		public FastWriter print(char c) { return write(c); }
		public FastWriter print(char[] s) { return write(s); }
		public FastWriter print(String s) { return write(s); }
		public FastWriter print(int x) { return write(x); }
		public FastWriter print(long x) { return write(x); }
		public FastWriter print(double x, int precision) { return write(x, precision); }
		public FastWriter println(char c){ return writeln(c); }
		public FastWriter println(int x){ return writeln(x); }
		public FastWriter println(long x){ return writeln(x); }
		public FastWriter println(double x, int precision){ return writeln(x, precision); }
		public FastWriter print(int... xs) { return write(xs); }
		public FastWriter print(long... xs) { return write(xs); }
		public FastWriter println(int... xs) { return writeln(xs); }
		public FastWriter println(long... xs) { return writeln(xs); }
		public FastWriter println(char[] line) { return writeln(line); }
		public FastWriter println(char[]... map) { return writeln(map); }
		public FastWriter println(String s) { return writeln(s); }
		public FastWriter println() { return writeln(); }
	}

	public void trnz(int... o)
	{
		for(int i = 0;i < o.length;i++)if(o[i] != 0)System.out.print(i+":"+o[i]+" ");
		System.out.println();
	}

	// print ids which are 1
	public void trt(long... o)
	{
		Queue<Integer> stands = new ArrayDeque<>();
		for(int i = 0;i < o.length;i++){
			for(long x = o[i];x != 0;x &= x-1)stands.add(i<<6|Long.numberOfTrailingZeros(x));
		}
		System.out.println(stands);
	}

	public void tf(boolean... r)
	{
		for(boolean x : r)System.out.print(x?'#':'.');
		System.out.println();
	}

	public void tf(boolean[]... b)
	{
		for(boolean[] r : b) {
			for(boolean x : r)System.out.print(x?'#':'.');
			System.out.println();
		}
		System.out.println();
	}

	public void tf(long[]... b)
	{
		if(INPUT.length() != 0) {
			for (long[] r : b) {
				for (long x : r) {
					for (int i = 0; i < 64; i++) {
						System.out.print(x << ~i < 0 ? '#' : '.');
					}
				}
				System.out.println();
			}
			System.out.println();
		}
	}

	public void tf(long... b)
	{
		if(INPUT.length() != 0) {
			for (long x : b) {
				for (int i = 0; i < 64; i++) {
					System.out.print(x << ~i < 0 ? '#' : '.');
				}
			}
			System.out.println();
		}
	}

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