import java.util.ArrayList;
import java.util.HashMap;

public class Euler867 {
    static final long MOD = 1000000007L;

    static long modPow(long a, long e) {
        long r = 1;
        while (e > 0) {
            if ((e & 1) == 1)
                r = (r * a) % MOD;
            a = (a * a) % MOD;
            e >>= 1;
        }
        return r;
    }

    static class Solver867 {
        int n;
        int maxLen;
        ArrayList<ArrayList<Integer>> indep;
        HashMap<String, Long> countCache;
        HashMap<Integer, Long> hCache;
        HashMap<Long, Long> fCache;
        HashMap<Long, Long> rCache;

        Solver867(int n) {
            this.n = n;
            this.maxLen = 2 * n - 1;
            this.indep = new ArrayList<>();
            for (int i = 0; i <= maxLen; ++i) {
                indep.add(new ArrayList<>());
            }
            this.countCache = new HashMap<>();
            this.hCache = new HashMap<>();
            this.fCache = new HashMap<>();
            this.rCache = new HashMap<>();
            buildIndependentMasks();
        }

        long pairKey(int a, int b) {
            return (((long) a) << 32) | ((long) b & 0xFFFFFFFFL);
        }

        void buildIndependentMasks() {
            for (int L = 0; L <= maxLen; ++L) {
                int lim = 1 << L;
                for (int m = 0; m < lim; ++m) {
                    if ((m & (m << 1)) == 0)
                        indep.get(L).add(m);
                }
            }
        }

        long[] zetaSubsetSum(long[] v, int L) {
            long[] out = v.clone();
            int size = 1 << L;
            for (int bit = 0; bit < L; ++bit) {
                int step = 1 << bit;
                int block = step << 1;
                for (int start = 0; start < size; start += block) {
                    int mid = start + step;
                    int end = start + block;
                    for (int m = mid; m < end; ++m) {
                        long x = out[m] + out[m - step];
                        out[m] = (x >= MOD ? x - MOD : x);
                    }
                }
            }
            return out;
        }

        String encodeLengths(ArrayList<Integer> lens) {
            StringBuilder sb = new StringBuilder();
            for (int x : lens) {
                sb.append(x).append("|");
            }
            return sb.toString();
        }

        long countIndependentSets(ArrayList<Integer> rowLengths) {
            String key = encodeLengths(rowLengths);
            if (countCache.containsKey(key))
                return countCache.get(key);

            if (rowLengths.isEmpty()) {
                countCache.put(key, 1L);
                return 1L;
            }

            int L0 = rowLengths.get(0);
            long[] dp = new long[1 << L0];
            for (int m : indep.get(L0))
                dp[m] = 1;

            for (int i = 1; i < rowLengths.size(); ++i) {
                int Lc = rowLengths.get(i - 1);
                int Ln = rowLengths.get(i);

                long[] subs = zetaSubsetSum(dp, Lc);
                long[] ndp = new long[1 << Ln];
                int full = (1 << Lc) - 1;

                if (Ln == Lc + 1) {
                    for (int b : indep.get(Ln)) {
                        int forb = (b | (b >> 1)) & full;
                        int allowed = full ^ forb;
                        ndp[b] = subs[allowed];
                    }
                } else {
                    for (int b : indep.get(Ln)) {
                        int forb = (b | (b << 1)) & full;
                        int allowed = full ^ forb;
                        ndp[b] = subs[allowed];
                    }
                }

                dp = ndp;
            }

            int lastL = rowLengths.get(rowLengths.size() - 1);
            long total = 0;
            for (int m : indep.get(lastL)) {
                total += dp[m];
                if (total >= MOD)
                    total -= MOD;
            }

            countCache.put(key, total);
            return total;
        }

        long H(int n) {
            if (hCache.containsKey(n))
                return hCache.get(n);

            ArrayList<Integer> lens = new ArrayList<>();
            for (int x = n; x <= 2 * n - 1; ++x)
                lens.add(x);
            for (int x = 2 * n - 2; x >= n; --x)
                lens.add(x);

            long val = countIndependentSets(lens);
            hCache.put(n, val);
            return val;
        }

        long F(int n, int h) {
            long key = pairKey(n, h);
            if (fCache.containsKey(key))
                return fCache.get(key);

            int rows = h - 1;
            ArrayList<Integer> lens = new ArrayList<>();
            for (int i = 0; i < Math.max(0, rows); ++i) {
                lens.add(Math.max(0, (n - 2) - i));
            }

            long val = countIndependentSets(lens);
            fCache.put(key, val);
            return val;
        }

        long R(int u, int v) {
            long key = pairKey(u, v);
            if (rCache.containsKey(key))
                return rCache.get(key);

            long res;
            if (v == 0) {
                res = H(u);
            } else {
                res = (u == 1 && v == 1) ? 1 : 0;
                for (int w = 0; w < u; ++w) {
                    long corner = F(u, u - w);
                    long add = (R(v, w) * modPow(corner, 6)) % MOD;
                    res += add;
                    if (res >= MOD)
                        res -= MOD;
                }
            }

            rCache.put(key, res);
            return res;
        }

        long T(int n) {
            long ans = (2L * R(n, n)) % MOD;
            if (n == 1)
                ans = (ans + MOD - 1) % MOD;
            return ans;
        }
    }

    public static String solve() {
        Solver867 solver = new Solver867(10);
        return Long.toString(solver.T(10));
    }

    public static void main(String[] args) {
        System.out.println(solve());
    }
}
