// package cf1181;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.BinaryOperator;
import java.util.function.Function;

import static java.util.Comparator.comparingInt;

public class CFE2 {
    private static final String INPUT = "14\n" +
            "4 17 6 20\n" +
            "9 17 10 20\n" +
            "12 17 20 18\n" +
            "10 15 11 16\n" +
            "0 11 3 20\n" +
            "10 13 11 14\n" +
            "11 4 16 15\n" +
            "11 18 19 20\n" +
            "4 5 10 15\n" +
            "10 4 11 13\n" +
            "0 0 16 3\n" +
            "17 0 20 16\n" +
            "0 7 3 8\n" +
            "0 4 3 6";
    private static final int MOD = 1_000_000_007;

    private PrintWriter out;
    private FastScanner sc;

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

    public void run() {
        sc = new FastScanner(oj ? System.in : new ByteArrayInputStream(INPUT.getBytes()));
        out = new PrintWriter(System.out);

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

    static class Rect {
        int x1, y1, x2, y2;
        boolean used;

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

        @Override
        public String toString() {
            return "{" + x1 + "," + y1 + "-" + x2 + "," + y2 + "}";
        }
    }

    static class Node {
        private Rect rect;
        private Node next;

        public Node(Rect rect) {
            this.rect = rect;
        }
    }

    static interface AreaFunc {
        int area(int area, Rect rect);

        default int _area(Rect rect) {
            int a1 = area(-1, rect);
            int a2 = area(Integer.MAX_VALUE, rect);

            return (a1 > -1) ? a1 : a2;
        }
    }

    static class Rects {
        private final AreaFunc areaFunc;
        private final BiPredicate<Integer, Rect> isSpace;

        Node root;
        Node curr;

        int currIdx;
        int area;

        public Rects(List<Rect> rects, Comparator<Rect> cmp, AreaFunc areaFunc, BiPredicate<Integer, Rect> isSpace) {
            this.areaFunc = areaFunc;
            this.isSpace = isSpace;
            rects.sort(cmp);
            root = new Node(rects.get(0));
            Node cur = root;
            for (int i = 1; i < rects.size(); i++) {
                Rect rect = rects.get(i);
                Node node = new Node(rect);
                cur.next = node;
                cur = node;
            }

            init();
        }

        private void init() {
            while (root.rect.used) root = root.next;
            curr = root;
            area = areaFunc._area(root.rect);
            currIdx = 1;
        }

        public void next() {
            curr = curr.next;
            while (curr.rect.used) curr = curr.next;
            currIdx++;
        }

        public boolean isSpace() {
            boolean test = isSpace.test(area, curr.rect);
            if (!test) area = areaFunc.area(area, curr.rect);
            return test;
        }

        List<Rect> drain() {
            Node node = root;
            List<Rect> res = new ArrayList<>(currIdx-1);
            for (int i = 1; i < currIdx; i++) {
                res.add(node.rect);
                node = node.next;
            }
            return res;
        }

        @Override
        public String toString() {
            Node node = root;
            StringBuilder res = new StringBuilder();
            while (node != null) {
                res.append(node.rect).append(" ");
                node = node.next;
            }
            return res.toString();
        }
    }

    static class Solver {
        int size;
        Rects[] rects = new Rects[4];

        public Solver(List<Rect> list) {
            size = list.size();
            if (size >= 4) {
                rects[0] = new Rects(list, comparingInt((Rect r) -> r.x1), (area, r) -> Math.max(area, r.x2), (a, r) -> a <= r.x1);
                rects[1] = new Rects(list, comparingInt((Rect r) -> -r.x2), (area, r) -> Math.min(area, r.x1), (a, r) -> a >= r.x2);
                rects[2] = new Rects(list, comparingInt((Rect r) -> r.y1), (area, r) -> Math.max(area, r.y2), (a, r) -> a <= r.y1);
                rects[3] = new Rects(list, comparingInt((Rect r) -> -r.y2), (area, r) -> Math.min(area, r.y1), (a, r) -> a >= r.y2);
            } else {
                for (Rect rect : list) {
                    rect.used = true;
                }
            }
        }

        boolean solve() {
            if (size < 4) {
                return true;
            }
            return _solve();
        }

        boolean _solve() {
            LOOP: while (size >= 4 && (rects[0].currIdx << 1) <= size) {
                for (int i = 0; i < 4; i++) {
                    Rects rect = rects[i];
                    rect.next();
                    if (rect.isSpace()) {
                        List<Rect> drain = rect.drain();
                        size -= drain.size();
                        boolean solve = new Solver(drain).solve();
                        if (!solve) return false;

                        for (int j = 0; j < 4; j++) {
                            rects[j].init();
                        }
                        continue LOOP;
                    }
                }
            }
            return size < 4;
        }
    }

    public void solve() {
        int n = sc.nextInt();
        List<Rect> list = new ArrayList<>(n);
        for (int i = 0; i < n; i++) {
            Rect rect = new Rect(sc.nextInt(), sc.nextInt(), sc.nextInt(), sc.nextInt());
            list.add(rect);
        }

        Solver solver = new Solver(list);
        System.out.println(solver.solve() ? "YES" : "NO");

    }

//********************************************************************************************
//********************************************************************************************
//********************************************************************************************

    static class SolutionFailedException extends Exception {
        int code;

        public SolutionFailedException(int code) {
            this.code = code;
        }
    }

    private static void shuffle(int[] array) {
        Random random = new Random();
        for (int i = array.length - 1; i > 0; i--) {
            int index = random.nextInt(i + 1);
            int temp = array[index];
            array[index] = array[i];
            array[i] = temp;
        }
    }

    /**
     * If searched element doesn't exist, returns index of first element which is bigger than searched value.

     * If searched element is bigger than any array element function returns first index after last element.

     * If searched element is lower than any array element function returns index of first element.

     * If there are many values equals searched value function returns first occurrence.

     */
    private static int lowerBound(long[] arr, long key) {
        int lo = 0;
        int hi = arr.length - 1;
        while (lo < hi) {
            int mid = (lo + hi) / 2;
            if (key <= arr[mid]) {
                hi = mid - 1;
            } else {
                lo = mid + 1;
            }
        }
        return arr[lo] < key ? lo + 1 : lo;
    }

    /**
     * Returns index of first element which is grater than searched value.
     * If searched element is bigger than any array element, returns first index after last element.
     */
    private static int upperBound(long[] arr, long key) {
        int lo = 0;
        int hi = arr.length - 1;
        while (lo < hi) {
            int mid = (lo + hi) / 2;
            if (key >= arr[mid]) {
                lo = mid + 1;
            } else {
                hi = mid;
            }
        }
        return arr[lo] <= key ? lo + 1 : lo;
    }

    private static int ceil(double d) {
        int ret = (int) d;
        return ret == d ? ret : ret + 1;
    }

    private static int round(double d) {
        return (int) (d + 0.5);
    }

    private static int gcd(int a, int b) {
        BigInteger b1 = BigInteger.valueOf(a);
        BigInteger b2 = BigInteger.valueOf(b);
        BigInteger gcd = b1.gcd(b2);
        return gcd.intValue();
    }

    private static long gcd(long a, long b) {
        BigInteger b1 = BigInteger.valueOf(a);
        BigInteger b2 = BigInteger.valueOf(b);
        BigInteger gcd = b1.gcd(b2);
        return gcd.longValue();
    }

    private int[] readIntArray(int n) {
        int[] res = new int[n];
        for (int i = 0; i < n; i++) {
            res[i] = sc.nextInt();
        }
        return res;
    }

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

    @SuppressWarnings("unused")
    static class FastScanner {
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;

        FastScanner(InputStream stream) {
            this.stream = stream;
        }

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

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

        boolean isEndline(int c) {
            return c == '\n' || c == '\r' || c == -1;
        }

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

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

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

        public String next() {
            int c = read();
            while (isSpaceChar(c)) c = read();
            StringBuilder res = new StringBuilder();
            do {
                res.appendCodePoint(c);
                c = read();
            } while (!isSpaceChar(c));
            return res.toString();
        }

        public String nextLine() {
            int c = read();
            while (isEndline(c))
                c = read();
            StringBuilder res = new StringBuilder();
            do {
                res.appendCodePoint(c);
                c = read();
            } while (!isEndline(c));
            return res.toString();
        }

    }

    private boolean oj = System.getProperty("ONLINE_JUDGE") != null;

    private void tr(Object... o) {
        if (!oj) System.out.println(Arrays.deepToString(o));
    }
}


// practice with rainboy
import java.io.*;
import java.util.*;

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

	static final int MD = 1000000007;
	int query(int[][] aa, int l0, int l1, int r0, int r1) {
		return l0 > l1 || r0 > r1 ? 0 : (int) ((long) aa[l1][r1] - aa[l0 - 1][r1] - aa[l1][r0 - 1] + aa[l0 - 1][r0 - 1]) % MD;
	}
	void add(int[][] aa, int l, int r, int a) {
		aa[l][r] = (aa[l][r] + a) % MD;
	}
	void main() {
		int n = sc.nextInt();
		int m = sc.nextInt();
		int[][] dp00 = new int[m + 1][m + 1];
		int[][] dp01 = new int[m + 1][m + 1];
		int[][] dp10 = new int[m + 1][m + 1];
		int[][] dp11 = new int[m + 1][m + 1];
		int[][] dq00 = new int[m + 1][m + 1];
		int[][] dq01 = new int[m + 1][m + 1];
		int[][] dq10 = new int[m + 1][m + 1];
		int[][] dq11 = new int[m + 1][m + 1];
		long ans = 0;
		while (n-- > 0) {
			for (int l = 1; l <= m; l++)
				for (int r = 1; r <= m; r++) {
					dp00[l][r] = (dp00[l][r] + dp00[l][r - 1]) % MD;
					dp01[l][r] = (dp01[l][r] + dp01[l][r - 1]) % MD;
					dp10[l][r] = (dp10[l][r] + dp10[l][r - 1]) % MD;
					dp11[l][r] = (dp11[l][r] + dp11[l][r - 1]) % MD;
				}
			for (int l = 1; l <= m; l++)
				for (int r = 1; r <= m; r++) {
					dp00[l][r] = (dp00[l][r] + dp00[l - 1][r]) % MD;
					dp01[l][r] = (dp01[l][r] + dp01[l - 1][r]) % MD;
					dp10[l][r] = (dp10[l][r] + dp10[l - 1][r]) % MD;
					dp11[l][r] = (dp11[l][r] + dp11[l - 1][r]) % MD;
				}
			for (int l = 1; l <= m; l++)
				for (int r = 1; r <= m; r++)
					dq00[l][r] = dq01[l][r] = dq10[l][r] = dq11[l][r] = 0;
			for (int l = 1; l <= m; l++)
				for (int r = l; r <= m; r++) {
					dq00[l][r] = 1;
					add(dq00, l, r, query(dp00, l, m, 1, r));
					add(dq01, l, r, query(dp01, l, r, r, m));
					add(dq01, l, r, query(dp00, l, r, r + 1, m));
					add(dq10, l, r, query(dp10, 1, l, l, r));
					add(dq10, l, r, query(dp00, 1, l - 1, l, r));
					add(dq11, l, r, query(dp11, 1, l, r, m));
					add(dq11, l, r, query(dp01, 1, l - 1, r, m));
					add(dq11, l, r, query(dp10, 1, l, r + 1, m));
					add(dq11, l, r, query(dp00, 1, l - 1, r + 1, m));
					ans = (ans + dq00[l][r] + dq01[l][r] + dq10[l][r] + dq11[l][r]) % MD;
				}
			int[][] tmp;
			tmp = dp00; dp00 = dq00; dq00 = tmp;
			tmp = dp01; dp01 = dq01; dq01 = tmp;
			tmp = dp10; dp10 = dq10; dq10 = tmp;
			tmp = dp11; dp11 = dq11; dq11 = tmp;
		}
		if (ans < 0)
			ans += MD;
		println(ans);
	}
}


import java.io.InputStreamReader;
import java.io.IOException;
import java.util.Arrays;
import java.util.InputMismatchException;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.Writer;
import java.io.InputStream;

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

class TaskD {
    public void solve(int testNumber, FastScanner in, FastPrinter out) {
        int n = in.nextInt();
        int m = in.nextInt();
        out.println(solve(n, m));
    }

    static final int MOD = 1000000007;

//    static int solveStupid(int n, int m) {
//        int[][][][][] dp = new int[m][2][2][n][n];
//        for (int i = 0; i < n; i++) {
//            for (int j = i; j < n; j++) {
//                dp[0][0][0][i][j] = 1;
//            }
//        }
//        for (int s = 1; s < m; s++) {
//            for (int i = 0; i < n; i++) {
//                for (int j = 0; j < m; j++) {
//
//                }
//            }
//        }
//    }

    static int solve(int n, int m) {
        int[][][][] dp = new int[2][2][n][n];
        int[][][][] next = new int[2][2][n][n];
        int ans = 0;
        for (int i = 0; i < m; i++) {
            for (int a = 0; a < 2; a++) {
                for (int b = 0; b < 2; b++) {
                    makePart(dp[a][b], n, n);
                    for (int[] d : next[a][b]) {
                        Arrays.fill(d, 0);
                    }
                }
            }
            {
                int[][] n00 = next[0][0];
                int[][] n01 = next[0][1];
                int[][] n10 = next[1][0];
                int[][] n11 = next[1][1];
                int[][] d00 = dp[0][0];
                int[][] d11 = dp[1][1];
                int[][] d10 = dp[1][0];
                int[][] d01 = dp[0][1];
                for (int c = 0; c < n; c++) {
                    for (int d = c; d < n; d++) {
                        n00[c][d] = getSum(d00, c, d + 1, c, d + 1);
                        n01[c][d] = getSum(d00, c, d + 1, d + 1, n) + getSum(d01, c, d + 1, d, n);
                        if (n01[c][d] >= MOD) {
                            n01[c][d] -= MOD;
                        }
                        n10[c][d] = getSum(d00, 0, c, c, d + 1) + getSum(d10, 0, c + 1, c, d + 1);
                        if (n10[c][d] >= MOD) {
                            n10[c][d] -= MOD;
                        }
                        int z = getSum(d00, 0, c, d + 1, n) + getSum(d01, 0, c, d, n);
                        if (z >= MOD) {
                            z -= MOD;
                        }
                        z += getSum(d10, 0, c + 1, d + 1, n) + getSum(d11, 0, c + 1, d, n);
                        if (z >= MOD) {
                            z -= MOD;
                        }
                        n11[c][d] = z;
                    }
                }
            }
            int[][] n00 = next[0][0];
            for (int c = 0; c < n; c++) {
                for (int d = c; d < n; d++) {
                    n00[c][d]++;
                    if (n00[c][d] >= MOD) {
                        n00[c][d] -= MOD;
                    }
                }
            }
            for (int a = 0; a < 2; a++) {
                for (int b = 0; b < 2; b++) {
                    int[][] nab = next[a][b];
                    for (int c = 0; c < n; c++) {
                        for (int d = 0; d < n; d++) {
                            ans += nab[c][d];
                            if (ans >= MOD) {
                                ans -= MOD;
                            }
                        }
                    }
                }
            }
            int[][][][] t = dp;
            dp = next;
            next = t;
        }
        return ans;
    }

    static void makePart(int[][] a, int b, int c) {
        for (int i = 1; i < b; i++) {
            for (int j = 0; j < c; j++) {
                a[i][j] += a[i - 1][j];
                if (a[i][j] >= MOD) {
                    a[i][j] -= MOD;
                }
            }
        }
        for (int i = 0; i < b; i++) {
            for (int j = 1; j < c; j++) {
                a[i][j] += a[i][j - 1];
                if (a[i][j] >= MOD) {
                    a[i][j] -= MOD;
                }
            }
        }
    }

    static int getSum(int[][] a, int x1, int x2, int y1, int y2) {
        if (x1 >= x2 || y1 >= y2) return 0;
        int ret = a[x2 - 1][y2 - 1];
        if (x1 > 0) {
            ret -= a[x1 - 1][y2 - 1];
            if (ret < 0) ret += MOD;
        }
        if (y1 > 0) {
            ret -= a[x2 - 1][y1 - 1];
            if (ret < 0) ret += MOD;
        }
        if (x1 > 0 && y1 > 0) {
            ret += a[x1 - 1][y1 - 1];
            if (ret >= MOD) ret -= MOD;
        }
        return ret;
    }
}

class FastScanner extends BufferedReader {

    boolean isEOF;

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

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

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

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

    }

class FastPrinter extends PrintWriter {

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

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

}


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

public class CF273D {

    final static int mod = 1000000007;

    static int[][] sum(int[][] a) {
        int n = a.length;
        int m = a[0].length;
        int[][] r = new int[n + 1][m + 1];
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= m; ++j) {
                r[i][j] = (r[i - 1][j] + r[i][j - 1]) % mod;
                r[i][j] = (r[i][j] + a[i - 1][j - 1]) % mod;
                r[i][j] = (r[i][j] + mod - r[i - 1][j - 1]) % mod;
            }
        }
        return r;
    }

    private static int[][] clone(int[][] a) {
        int n = a.length;
        int m = a[0].length;
        int[][] r = new int[n][m];
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < m; ++j) {
                r[i][j] = a[i][j];
            }
        }
        return r;
    }

    public static void solve(Input in, PrintWriter out) throws IOException {
        int n = in.nextInt();
        int m = in.nextInt();
        int[][] d00 = new int[m][m];
        int[][] d01 = new int[m][m];
        int[][] d10 = new int[m][m];
        int[][] d11 = new int[m][m];
        long ans = 0;
        for (int it = 0; it <= n; ++it) {
            int[][] s00 = sum(d00);
            int[][] s01 = sum(d01);
            int[][] s10 = sum(d10);
            int[][] s11 = sum(d11);
//            int[][] s00 = clone(d00);
//            int[][] s01 = clone(d01);
//            int[][] s10 = clone(d10);
//            int[][] s11 = clone(d11);
            for (int u = 0; u < m; ++u) {
                for (int v = u; v < m; ++v) {
                    ans = (ans + d00[u][v]) % mod;
                    ans = (ans + d01[u][v]) % mod;
                    ans = (ans + d10[u][v]) % mod;
                    ans = (ans + d11[u][v]) % mod;
                }
            }
//            System.err.println(Arrays.deepToString(d00));
//            System.err.println(Arrays.deepToString(d01));
//            System.err.println(Arrays.deepToString(d10));
//            System.err.println(Arrays.deepToString(d11));
            for (int u = 0; u < m; ++u) {
                for (int v = u; v < m; ++v) {
                    d00[u][v] = d01[u][v] = d10[u][v] = d11[u][v] = 0;

                    d00[u][v] = (d00[u][v] + sum(s00, u, m - 1, u, v));
//                    for (int u1 = u; u1 < m; ++u1) {
//                        for (int v1 = u1; v1 <= v; ++v1) {
//                            d00[u][v] = (d00[u][v] + s00[u1][v1]) % mod;
//                        }
//                    }

                    d01[u][v] = (d01[u][v] + sum(s00, u, v, v + 1, m - 1));
//                    for (int u1 = u; u1 <= v; ++u1) {
//                        for (int v1 = v + 1; v1 < m; ++v1) {
//                            d01[u][v] = (d01[u][v] + s00[u1][v1]) % mod;
//                        }
//                    }
                    d01[u][v] = (d01[u][v] + sum(s01, u, v, v, m - 1));
//                    for (int u1 = u; u1 <= v; ++u1) {
//                        for (int v1 = v; v1 < m; ++v1) {
//                            d01[u][v] = (d01[u][v] + s01[u1][v1]) % mod;
//                        }
//                    }

                    d10[u][v] = (d10[u][v] + sum(s00, 0, u - 1, u, v));
//                    for (int u1 = 0; u1 < u; ++u1) {
//                        for (int v1 = u; v1 <= v; ++v1) {
//                            d10[u][v] = (d10[u][v] + s00[u1][v1]) % mod;
//                        }
//                    }
                    d10[u][v] = (d10[u][v] + sum(s10, 0, u, u, v));
//                    for (int u1 = 0; u1 <= u; ++u1) {
//                        for (int v1 = u; v1 <= v; ++v1) {
//                            d10[u][v] = (d10[u][v] + s10[u1][v1]) % mod;
//                        }
//                    }

                    d11[u][v] = (d11[u][v] + sum(s00, 0, u - 1, v + 1, m - 1));
//                    for (int u1 = 0; u1 < u; ++u1) {
//                        for (int v1 = v + 1; v1 < m; ++v1) {
//                            d11[u][v] = (d11[u][v] + s00[u1][v1]) % mod;
//                        }
//                    }
                    d11[u][v] = (d11[u][v] + sum(s01, 0, u - 1, v, m - 1));
//                    for (int u1 = 0; u1 < u; ++u1) {
//                        for (int v1 = v; v1 < m; ++v1) {
//                            d11[u][v] = (d11[u][v] + s01[u1][v1]) % mod;
//                        }
//                    }
                    d11[u][v] = (d11[u][v] + sum(s10, 0, u, v + 1, m - 1));
//                    for (int u1 = 0; u1 <= u; ++u1) {
//                        for (int v1 = v + 1; v1 < m; ++v1) {
//                            d11[u][v] = (d11[u][v] + s10[u1][v1]) % mod;
//                        }
//                    }
                    d11[u][v] = (d11[u][v] + sum(s11, 0, u, v, m - 1));
//                    for (int u1 = 0; u1 <= u; ++u1) {
//                        for (int v1 = v; v1 < m; ++v1) {
//                            d11[u][v] = (d11[u][v] + s11[u1][v1]) % mod;
//                        }
//                    }
                    d00[u][v] = (d00[u][v] + 1) % mod;
                }
            }
        }
        out.println(ans);
    }

    private static int sum(int[][] s, int i1, int i2, int j1, int j2) {
        int r = s[i2 + 1][j2 + 1];
        r = (r + mod - s[i2 + 1][j1]) % mod;
        r = (r + mod - s[i1][j2 + 1]) % mod;
        r = (r + s[i1][j1]) % mod;
        return r;
    }

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

    static class Input {
        BufferedReader in;
        StringTokenizer st;

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

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

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

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

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

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

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


import java.math.BigInteger;
import java.util.*;

public class Main {
    static final int MOD = 1000000007;

    public static int count(int height , int width) {
        boolean[][] field = new boolean[height][width];
        int[][][][] res = new int[2][2][width][width];
        int tR = 0;
        for (int row = 0; row < height; ++row) {
            int[][][][] newRes = new int[2][2][width][width];
            for (int fD = 0; fD < 2; ++fD)
                for (int lD = 0; lD < 2; ++lD)
                    for (int fC = 0; fC < width; ++fC)
                        for (int lC = fC; lC < width; ++lC) {
                            int cur = res[fD][lD][fC][lC];
                            if (cur == 0) continue;
                            for (int newfD = fD; newfD < 2; ++newfD)
                                for (int newlD = lD; newlD < 2; ++newlD) {
                                    int nF;
                                    if (newfD == 0)
                                        nF = fC;
                                    else if (fD == 0)
                                        nF = fC + 1;
                                    else
                                        nF = fC;
                                    int nL;
                                    if (newlD == 0)
                                        nL = lC;
                                    else if (lD == 0)
                                        nL = lC - 1;
                                    else
                                        nL = lC;
                                    if (nF > nL)
                                        continue;
                                    int[] arr = newRes[newfD][newlD][nF];
                                    arr[nL] += cur;
                                    if (arr[nL] >= MOD) arr[nL] -= MOD;
                                }
                        }

            for (int fD = 0; fD < 2; ++fD)
                for (int lD = 0; lD < 2; ++lD) {
                    int[][] arr = newRes[fD][lD];
                    if (fD == 0 && lD == 1) {
                        {
                            int lD = lD == 0 ? 1 : -1;
                            int lM = lD == 1 ? 0 : width - 1;
                            int lMax = lD == 1 ? width : -1;
                            for (int lC = lM; lC != lMax; lC += lD) {
                                for (int fC = 0; fC <= lC; ++fC) {
                                    int cur = arr[fC][lC];
                                    if (cur == 0) continue;
                                    int nL = lC + lD;
                                    if (nL >= fC && nL < width) {
                                        arr[fC][nL] += cur;
                                        if (arr[fC][nL] >= MOD) arr[fC][nL] -= MOD;
                                    }
                                }
                            }
                        }
                        {
                            int fD = fD == 0 ? -1 : 1;
                            int fM = fD == 1 ? 0 : width - 1;
                            int fM = fD == 1 ? width : -1;
                            for (int fC = fM; fC != fM; fC += fD) {
                                for (int lC = fC; lC < width; ++lC) {
                                    int cur = arr[fC][lC];
                                    if (cur == 0) continue;
                                    int nF = fC + fD;
                                    if (nF >= 0 && nF <= lC) {
                                        arr[nF][lC] += cur;
                                        if (arr[nF][lC] >= MOD) arr[nF][lC] -= MOD;
                                    }
                                }
                            }
                        }
                    } else {
                        {
                            int fD = fD == 0 ? -1 : 1;
                            int fM = fD == 1 ? 0 : width - 1;
                            int fM = fD == 1 ? width : -1;
                            for (int fC = fM; fC != fM; fC += fD) {
                                for (int lC = fC; lC < width; ++lC) {
                                    int cur = arr[fC][lC];
                                    if (cur == 0) continue;
                                    int nF = fC + fD;
                                    if (nF >= 0 && nF <= lC) {
                                        arr[nF][lC] += cur;
                                        if (arr[nF][lC] >= MOD) arr[nF][lC] -= MOD;
                                    }
                                }
                            }
                        }
                        {
                            int lD = lD == 0 ? 1 : -1;
                            int lM = lD == 1 ? 0 : width - 1;
                            int lMax = lD == 1 ? width : -1;
                            for (int lC = lM; lC != lMax; lC += lD) {
                                for (int fC = 0; fC <= lC; ++fC) {
                                    int cur = arr[fC][lC];
                                    if (cur == 0) continue;
                                    int nL = lC + lD;
                                    if (nL >= fC && nL < width) {
                                        arr[fC][nL] += cur;
                                        if (arr[fC][nL] >= MOD) arr[fC][nL] -= MOD;
                                    }
                                }
                            }
                        }
                    }
                }

            for (int fC = 0; fC < width; ++fC) {
                boolean ok = true;
                for (int lC = fC; lC < width; ++lC) {
                    if (field[row][lC])
                        ok = false;
                    if (!ok) {
                        for (int fD = 0; fD < 2; ++fD)
                            for (int lD = 0; lD < 2; ++lD)
                                newRes[fD][lD][fC][lC] = 0;
                   } else {
                        newRes[0][0][fC][lC] += 1;
                        if (newRes[0][0][fC][lC] >= MOD) newRes[0][0][fC][lC] -= MOD;
                    }
                }
            }

            res = newRes;
            for (int fD = 0; fD < 2; ++fD)
                for (int lD = 0; lD < 2; ++lD)
                    for (int fC = 0; fC < width; ++fC)
                        for (int lC = fC; lC < width; ++lC) {
                            tR += res[fD][lD][fC][lC];
                            if (tR >= MOD) tR -= MOD;
                        }
        }
        return tR;
    }
    public static void main(String[] args){
        Scanner cin = new Scanner(System.in);
        int n = cin.nextInt() , m = cin.nextInt();
        System.out.println(count(n, m));
    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.AbstractSet;
import java.util.InputMismatchException;
import java.util.Random;
import java.util.ArrayList;
import java.util.AbstractCollection;
import java.util.Map;
import java.io.OutputStreamWriter;
import java.util.NoSuchElementException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Iterator;
import java.io.BufferedWriter;
import java.util.Collection;
import java.util.Set;
import java.io.IOException;
import java.util.List;
import java.util.AbstractMap;
import java.io.Writer;
import java.util.Map.Entry;
import java.util.Comparator;
import java.io.InputStream;

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

    static class FShadyLady {
        public void solve(int testNumber, InputReader in, OutputWriter out) {
            int n = in.readInt();
            int[] A = new int[n], B = new int[n];
            in.readIntArrays(A, B);
            int hasOrigin = 0;
            for (int i = 0; i < n; i++) {
                if (A[i] == 0 && B[i] == 0) {
                    hasOrigin = 1;
                    break;
                }
            }
            Point[] points = new Point[n + 1 - hasOrigin];
            Arrays.setAll(points, i -> (i < n ? new Point(A[i], B[i]) : Point.ORIGIN));
            Polygon total = Polygon.convexHull(points, true);
            boolean lose = check(total);
            Set<Point> even = new EHashSet<>(), odd = new EHashSet<>();
            for (int i = 0; i < total.vertices.length; i++) {
                Point P = total.vertices[i];
                if (P.equals(Point.ORIGIN)) {
                    continue;
                }
                if (i % 2 == 0) {
                    even.add(P);
                } else {
                    odd.add(P);
                }
            }
            List<Point> notEven = new ArrayList(), notOdd = new ArrayList<>();
            for (Point P : points) {
                if (!even.contains(P)) {
                    notEven.add(P);
                }
                if (!odd.contains(P)) {
                    notOdd.add(P);
                }
            }
            Point[] notEvenArray = notEven.toArray(new Point[0]), notOddArray = notOdd.toArray(new Point[0]);
            Polygon notEvenPolygon = Polygon.convexHull(notEvenArray, true), notOddPolygon = Polygon.convexHull(notOddArray, true);
            lose |= check(notEvenPolygon);
            lose |= check(notOddPolygon);
            out.printLine(lose ? "Ani" : "Borna");
        }

        boolean check(Polygon poly) {
            for (Point p : poly.vertices) {
                long x = Math.round(p.x), y = Math.round(p.y);
                if (x % 2 == 1 || y % 2 == 1) {
                    return true;
                }
            }
            return false;
        }

    }

    static class OutputWriter {
        private final PrintWriter writer;

        public OutputWriter(OutputStream outputStream) {
            writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
        }

        public OutputWriter(Writer writer) {
            this.writer = new PrintWriter(writer);
        }

        public void print(Object... objects) {
            for (int i = 0; i < objects.length; i++) {
                if (i != 0) {
                    writer.print(' ');
                }
                writer.print(objects[i]);
            }
        }

        public void printLine(Object... objects) {
            print(objects);
            writer.println();
        }

        public void close() {
            writer.close();
        }

    }

    static class Polygon {
        public final Point[] vertices;

        public Polygon(Point... vertices) {
            this.vertices = vertices.clone();
        }

        public static boolean over(Point a, Point b, Point c) {
            return a.x * (b.y - c.y) + b.x * (c.y - a.y) + c.x * (a.y - b.y) < -GeometryUtils.epsilon;
        }

        private static boolean under(Point a, Point b, Point c) {
            return a.x * (b.y - c.y) + b.x * (c.y - a.y) + c.x * (a.y - b.y) > GeometryUtils.epsilon;
        }

        public static Polygon convexHull(Point[] points, boolean strict) {
            if (points.length == 1) {
                return new Polygon(points);
            }
            Arrays.sort(points, Comparator.comparingDouble((Point o) -> o.x).thenComparingDouble(o -> o.y));
            Point left = points[0];
            Point right = points[points.length - 1];
            List<Point> up = new ArrayList<>();
            List<Point> down = new ArrayList<>();
            for (Point point : points) {
                if (point == left || point == right || (strict ? over(left, point, right) : !under(left, point, right))) {
                    while (up.size() >= 2 && (strict ? !over(up.get(up.size() - 2), up.get(up.size() - 1), point) : under(up.get(up.size() - 2), up.get(up.size() - 1), point))) {
                        up.remove(up.size() - 1);
                    }
                    up.add(point);
                }
                if (point == left || point == right || (strict ? under(left, point, right) : !over(left, point, right))) {
                    while (down.size() >= 2 && (strict ? !under(down.get(down.size() - 2), down.get(down.size() - 1), point) : over(down.get(down.size() - 2), down.get(down.size() - 1), point))) {
                        down.remove(down.size() - 1);
                    }
                    down.add(point);
                }
            }
            Point[] result = new Point[up.size() + down.size() - 2];
            int index = 0;
            for (Point point : up) {
                result[index++] = point;
            }
            for (int i = down.size() - 2; i > 0; i--) {
                result[index++] = down.get(i);
            }
            return new Polygon(result);
        }

    }

    static class EHashSet<E> extends AbstractSet<E> {
        private static final Object VALUE = new Object();
        private final Map<E, Object> map;

        public EHashSet() {
            this(4);
        }

        public EHashSet(int maxSize) {
            map = new EHashMap<>(maxSize);
        }

        public EHashSet(Collection<E> collection) {
            this(collection.size());
            addAll(collection);
        }

        public boolean contains(Object o) {
            return map.containsKey(o);
        }

        public boolean add(E e) {
            if (e == null) {
                return false;
            }
            return map.put(e, VALUE) == null;
        }

        public boolean remove(Object o) {
            if (o == null) {
                return false;
            }
            return map.remove(o) != null;
        }

        public void clear() {
            map.clear();
        }

        public Iterator<E> iterator() {
            return map.keySet().iterator();
        }

        public int size() {
            return map.size();
        }

    }

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

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

        public void readIntArrays(int[]... arrays) {
            for (int i = 0; i < arrays[0].length; i++) {
                for (int j = 0; j < arrays.length; j++) {
                    arrays[j][i] = readInt();
                }
            }
        }

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

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

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

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

        public interface SpaceCharFilter {
            boolean isSpaceChar(int ch);

        }

    }

    static class EHashMap<E, V> extends AbstractMap<E, V> {
        private static final int[] shifts = new int[10];
        private int size;
        private EHashMap.HashEntry<E, V>[] data;
        private int capacity;
        private Set<Entry<E, V>> entrySet;

        static {
            Random random = new Random(System.currentTimeMillis());
            for (int i = 0; i < 10; i++) {
                shifts[i] = 1 + 3 * i + random.nextInt(3);
            }
        }

        public EHashMap() {
            this(4);
        }

        private void setCapacity(int size) {
            capacity = Integer.highestOneBit(4 * size);
            //noinspection unchecked
            data = new EHashMap.HashEntry[capacity];
        }

        public EHashMap(int maxSize) {
            setCapacity(maxSize);
            entrySet = new AbstractSet<Entry<E, V>>() {

                public Iterator<Entry<E, V>> iterator() {
                    return new Iterator<Entry<E, V>>() {
                        private EHashMap.HashEntry<E, V> last = null;
                        private EHashMap.HashEntry<E, V> current = null;
                        private EHashMap.HashEntry<E, V> base = null;
                        private int lastIndex = -1;
                        private int index = -1;

                        public boolean hasNext() {
                            if (current == null) {
                                for (index++; index < capacity; index++) {
                                    if (data[index] != null) {
                                        base = current = data[index];
                                        break;
                                    }
                                }
                            }
                            return current != null;
                        }

                        public Entry<E, V> next() {
                            if (!hasNext()) {
                                throw new NoSuchElementException();
                            }
                            last = current;
                            lastIndex = index;
                            current = current.next;
                            if (base.next != last) {
                                base = base.next;
                            }
                            return last;
                        }

                        public void remove() {
                            if (last == null) {
                                throw new IllegalStateException();
                            }
                            size--;
                            if (base == last) {
                                data[lastIndex] = last.next;
                            } else {
                                base.next = last.next;
                            }
                        }
                    };
                }

                public int size() {
                    return size;
                }
            };
        }

        public EHashMap(Map<E, V> map) {
            this(map.size());
            putAll(map);
        }

        public Set<Entry<E, V>> entrySet() {
            return entrySet;
        }

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

        private int index(Object o) {
            return getHash(o.hashCode()) & (capacity - 1);
        }

        private int getHash(int h) {
            int result = h;
            for (int i : shifts) {
                result ^= h >>> i;
            }
            return result;
        }

        public V remove(Object o) {
            if (o == null) {
                return null;
            }
            int index = index(o);
            EHashMap.HashEntry<E, V> current = data[index];
            EHashMap.HashEntry<E, V> last = null;
            while (current != null) {
                if (current.key.equals(o)) {
                    if (last == null) {
                        data[index] = current.next;
                    } else {
                        last.next = current.next;
                    }
                    size--;
                    return current.value;
                }
                last = current;
                current = current.next;
            }
            return null;
        }

        public V put(E e, V value) {
            if (e == null) {
                return null;
            }
            int index = index(e);
            EHashMap.HashEntry<E, V> current = data[index];
            if (current != null) {
                while (true) {
                    if (current.key.equals(e)) {
                        V oldValue = current.value;
                        current.value = value;
                        return oldValue;
                    }
                    if (current.next == null) {
                        break;
                    }
                    current = current.next;
                }
            }
            if (current == null) {
                data[index] = new EHashMap.HashEntry<>(e, value);
            } else {
                current.next = new EHashMap.HashEntry<>(e, value);
            }
            size++;
            if (2 * size > capacity) {
                EHashMap.HashEntry<E, V>[] oldData = data;
                setCapacity(size);
                for (EHashMap.HashEntry<E, V> entry : oldData) {
                    while (entry != null) {
                        EHashMap.HashEntry<E, V> next = entry.next;
                        index = index(entry.key);
                        entry.next = data[index];
                        data[index] = entry;
                        entry = next;
                    }
                }
            }
            return null;
        }

        public V get(Object o) {
            if (o == null) {
                return null;
            }
            int index = index(o);
            EHashMap.HashEntry<E, V> current = data[index];
            while (current != null) {
                if (current.key.equals(o)) {
                    return current.value;
                }
                current = current.next;
            }
            return null;
        }

        public boolean containsKey(Object o) {
            if (o == null) {
                return false;
            }
            int index = index(o);
            EHashMap.HashEntry<E, V> current = data[index];
            while (current != null) {
                if (current.key.equals(o)) {
                    return true;
                }
                current = current.next;
            }
            return false;
        }

        public int size() {
            return size;
        }

        private static class HashEntry<E, V> implements Entry<E, V> {
            private final E key;
            private V value;
            private EHashMap.HashEntry<E, V> next;

            private HashEntry(E key, V value) {
                this.key = key;
                this.value = value;
            }

            public E getKey() {
                return key;
            }

            public V getValue() {
                return value;
            }

            public V setValue(V value) {
                V oldValue = this.value;
                this.value = value;
                return oldValue;
            }

        }

    }

    static class Point {
        public static final Point ORIGIN = new Point(0, 0);
        public final double x;
        public final double y;

        public String toString() {
            return "(" + x + ", " + y + ")";
        }

        public Point(double x, double y) {
            this.x = x;
            this.y = y;
        }

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

            Point point = (Point) o;

            return Math.abs(x - point.x) <= GeometryUtils.epsilon && Math.abs(y - point.y) <= GeometryUtils.epsilon;
        }

        public int hashCode() {
            int result;
            long temp;
            temp = x != +0.0d ? Double.doubleToLongBits(x) : 0L;
            result = (int) (temp ^ (temp >>> 32));
            temp = y != +0.0d ? Double.doubleToLongBits(y) : 0L;
            result = 31 * result + (int) (temp ^ (temp >>> 32));
            return result;
        }

    }

    static class GeometryUtils {
        public static double epsilon = 1e-8;

    }
}


import java.io.*;
import java.math.BigInteger;
public class flags{
public static int mod = 1000000007,modi = (mod+1)>>1;
public static BigInteger modB = new BigInteger("1000000007");
public static BigInteger modiB = new BigInteger("500000004");
public static long id[][] ={{1,0,0,0,0,0,0},{0,1,0,0,0,0,0},{0,0,1,0,0,0,0},{0,0,0,1,0,0,0},{0,0,0,0,1,0,0},{0,0,0,0,0,1,0},{0,0,0,0,0,0,1}};
public static long a[][] = {{1,0,0,0,0,0,0},{1,0,0,0,0,0,0},{1,1,0,0,1,1,0},{1,1,0,0,1,0,1},{1,0,1,1,0,0,0},{0,0,1,0,0,0,0},{0,0,0,1,0,0,0}};//adyacencia aut
public static void main(String args[]) throws IOException{
BufferedReader lector= new BufferedReader(new InputStreamReader(System.in));
//for(int n = Integer.parseInt(args[0]);n<1000000001;n++)
String tmp = lector.readLine();
int n2 = Integer.parseInt(tmp.substring(0,tmp.indexOf(" ")))-1;
int n1 = Integer.parseInt(tmp.substring(tmp.indexOf(" ")+1));
BigInteger un = f(a,n1);
BigInteger dos = f(a,n1/2+(n1&1));
un = ((un.subtract(dos).multiply(modiB)).add(dos)).mod(modB);
BigInteger un1 = f(a,n2);
BigInteger dos1 = f(a,n2/2+(n2&1));
un1 = ((un1.subtract(dos1).multiply(modiB)).add(dos1)).mod(modB);
BigInteger joder = un.subtract(un1);
System.out.println(joder);
}
public static BigInteger f(long a[][],int n){
long p[][] = exp(a,n);
BigInteger res = BigInteger.ZERO;
int ri[] = {0,1,1,1,1,1,1};//terminales de cada nodo
for(int nn = 0;nn<p.length;nn++)res=(res.add(new BigInteger(""+p[nn][0]).multiply(new BigInteger(""+ri[nn])))).mod(modB);
return res.mod(modB);
/*
//if((n&1)==1){
p = exp(a,n/2+1);
int r[] = {0,1,1,1,1,1,1};
//int r[] = {4,2,2,2,2,1,1};//terminales de cada nodo
BigInteger res2 = BigInteger.ZERO;
for(int nn = 0;nn<p.length;nn++)res2=(res2.add(new BigInteger(""+p[nn][0]).multiply(new BigInteger(""+r[nn])))).mod(modB);
return (((res.subtract(res2)).multiply(modiB)).mod(modB).add(res2)).mod(modB);
//}
//return (res.multiply(modiB)).mod(modB);
*/
}
public static long[][] mul(long[][] a,long[][] b){
long res[][] = new long[a.length][b[0].length];
for(int n = 0;n<res.length;n++)
for(int m = 0;m<res[n].length;m++){
long tal = 0;
for(int x = 0;x<res[0].length;x++)
tal = (tal+a[n][x]*b[x][m])%mod;
res[n][m]=tal;
}
return res;
}
public static long[][] exp(long[][] a,int b){
if(b==0)
return id;
if(b==1)return a;
if((b&1)==0)
return exp(mul(a,a),b/2);
return mul(exp(mul(a,a),b/2),a);
}
}


import java.util.*;
import java.util.regex.*;
import java.io.*;
import java.math.BigInteger;
import static java.lang.Math.*;

public class Sol implements Runnable {
	final long MOD = 1000000007;
	long half = (MOD + 1) / 2;

	void solve() throws Exception {
		int L = nextInt(), R = nextInt();
		long ans = ((getGoodAll(R) - getGoodAll(L - 1) + MOD) * half) % MOD;
		out.println(ans);
	}

	long get(int n) {
		return 2 * getK(n) + 2 * getY(n);
	}

	long getAll(int R) {
		long res = get(1);
		if (R == 1) return res;
		res += 2 * getK(R) + 4 * getK(1);
		res %= MOD;
		long add1 = R >= 3 ? 6 * (mpow(3, (R - 1) / 2) - 1) : 0;
		long add2 = R >= 4 ? 3 * (mpow(3, (R + 1) / 2) - 3) : 0;
		return (res + add1 + add2) % MOD;
	}

	long getGoodAll(int R) {
		if (R == 0) return 0;
		long res = getAll(R);
		res += getAll((R + 1) / 2);
		return res % MOD;
	}

	long getGood(int n) {
		long ret = get(n);
		if (n % 2 == 1) {
			ret += get((n + 1) / 2);
		}
		return ret / 2;
	}

	long getY(int n) {
		return n == 1 ? 1 : 2 * getK(n - 1);
	}

	long getK(int n) {
		if (n % 2 == 0) {
			return (2 * mpow(3, n / 2 - 1)) % MOD;
		} else {
			return mpow(3, n / 2);
		}
	}

	long mpow(long a, long n) {
		if (n == 0) return 1;
		long ans = mpow(a, n / 2);
		ans = (ans * ans) % MOD;
		if (n % 2 == 1) {
			ans = (ans * a) % MOD;
		}
		return ans;
	}

	public static void main(String[] args) {
		new Thread(new Sol()).start();
	}

	public void run() {
		try {
			Locale.setDefault(Locale.US);
			in = new BufferedReader(new InputStreamReader(System.in));
			out = new PrintWriter(System.out);
			solve();

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

	StringTokenizer tokenizer = new StringTokenizer("");
	BufferedReader in;
	PrintWriter out;
	long time;

	void sTime() {
		time = System.currentTimeMillis();
	}

	long gTime() {
		return System.currentTimeMillis() - time;
	}

	void gMemory() {
		debug("Memory: " + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1000 + " kb");
	}

	public void debug(Object o) {
		System.err.println(o);
	}

	boolean seekForToken() {
		while (!tokenizer.hasMoreTokens()) {
			String s = null;
			try {
				s = in.readLine();
			} catch (Exception e) {
				e.printStackTrace();
			}
			if (s == null)
				return false;
			tokenizer = new StringTokenizer(s);
		}
		return true;
	}

	String nextToken() {
		return seekForToken() ? tokenizer.nextToken() : null;
	}

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

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

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

	BigInteger nextBig() {
		return new BigInteger(nextToken());
	}
}


import java.util.*;
import java.util.regex.*;
import java.io.*;
import java.math.BigInteger;
import static java.lang.Math.*;

public class Sol implements Runnable {
	final long MOD = 1000000007;
	long half = (MOD + 1) / 2;

	void solve() throws Exception {
		int L = nextInt(), R = nextInt();
		long ans = (((getGoodAll(R) - getGoodAll(L - 1) + MOD) * half) % MOD + MOD) % MOD;
		out.println(ans);
	}

	long get(int n) {
		return 2 * getK(n) + 2 * getY(n);
	}

	long getAll(int R) {
		long res = get(1);
		if (R == 1) return res;
		res += 2 * getK(R) + 4 * getK(1);
		res %= MOD;
		long add1 = R >= 3 ? 6 * (mpow(3, (R - 1) / 2) - 1) : 0;
		long add2 = R >= 4 ? 3 * (mpow(3, (R + 1) / 2) - 3) : 0;
		return (res + add1 + add2) % MOD;
	}

	long getGoodAll(int R) {
		if (R == 0) return 0;
		long res = getAll(R);
		res += getAll((R + 1) / 2);
		return res % MOD;
	}

	long getGood(int n) {
		long ret = get(n);
		if (n % 2 == 1) {
			ret += get((n + 1) / 2);
		}
		return ret / 2;
	}

	long getY(int n) {
		return n == 1 ? 1 : 2 * getK(n - 1);
	}

	long getK(int n) {
		if (n % 2 == 0) {
			return (2 * mpow(3, n / 2 - 1)) % MOD;
		} else {
			return mpow(3, n / 2);
		}
	}

	long mpow(long a, long n) {
		if (n == 0) return 1;
		long ans = mpow(a, n / 2);
		ans = (ans * ans) % MOD;
		if (n % 2 == 1) {
			ans = (ans * a) % MOD;
		}
		return ans;
	}

	public static void main(String[] args) {
		new Thread(new Sol()).start();
	}

	public void run() {
		try {
			Locale.setDefault(Locale.US);
			in = new BufferedReader(new InputStreamReader(System.in));
			out = new PrintWriter(System.out);
			solve();

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

	StringTokenizer tokenizer = new StringTokenizer("");
	BufferedReader in;
	PrintWriter out;
	long time;

	void sTime() {
		time = System.currentTimeMillis();
	}

	long gTime() {
		return System.currentTimeMillis() - time;
	}

	void gMemory() {
		debug("Memory: " + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1000 + " kb");
	}

	public void debug(Object o) {
		System.err.println(o);
	}

	boolean seekForToken() {
		while (!tokenizer.hasMoreTokens()) {
			String s = null;
			try {
				s = in.readLine();
			} catch (Exception e) {
				e.printStackTrace();
			}
			if (s == null)
				return false;
			tokenizer = new StringTokenizer(s);
		}
		return true;
	}

	String nextToken() {
		return seekForToken() ? tokenizer.nextToken() : null;
	}

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

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

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

	BigInteger nextBig() {
		return new BigInteger(nextToken());
	}
}


import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.*;

public class CofeForces {
    public static void main(String[] args) throws FileNotFoundException {
        Scanner in = new Scanner(System.in);
        PrintWriter out = new PrintWriter(System.out);
        long n = in.nextLong(), m = in.nextLong(), a = in.nextLong(), b = in.nextLong();
        a--;
        b--;
        int ans = -1;
        if (a / m == b / m) ans = 1; else {
            a = a%m;
            if (a == 0 && b%m == (m-1)) ans = 1;
            else if (a == 0 && b == n-1) ans = 1;
            else if (a == 0 || b%m == (m-1) || b == n-1) ans = 2;
            else if ((a%m) == (b%m)+1) ans = 2;
            else ans = 3;
        }

        System.out.println( ans );
        out.close();
    }

}


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

public class _LiftLevel5E {

	static boolean[][] locked;
	static int[][] board;
	static int[][] solved;
	static int w, h;
	static ArrayList<String> answer=new ArrayList<>();

	public static void main(String[] args) {
		FastScanner fs=new FastScanner();
		h=fs.nextInt(); w=fs.nextInt();
		board=new int[w][h];
		solved=new int[w][h];
		locked=new boolean[w][h];
		for (int y=0; y<h; y++) {
			for (int x=0; x<w; x++) {
				board[x][y]=fs.nextInt();
				solved[x][y]=x+y*w+1;
			}
		}
		//solve ys [0, h-2)
		for (int yToSolveFor=0; yToSolveFor<h-2; yToSolveFor++) {
			for (int xToSolveFor=0; xToSolveFor<w-1; xToSolveFor++) {
				naiveMoveToXFirst(solved[xToSolveFor][yToSolveFor], xToSolveFor, yToSolveFor);
				locked[xToSolveFor][yToSolveFor]=true;
			}
			//now handle the rightmost position
			if (board[w-1][yToSolveFor]==solved[w-1][yToSolveFor]) {
				locked[w-1][yToSolveFor]=true;
				continue;
			}
			naiveMoveToXFirst(solved[w-1][yToSolveFor], w-1, h-1);
			hardCW4(w-2, yToSolveFor);
			naiveMoveToXFirst(solved[w-1][yToSolveFor], w-1, yToSolveFor+1);
			hardCCW4(w-2, yToSolveFor);
			locked[w-2][yToSolveFor]=locked[w-1][yToSolveFor]=true;
		}
//		print(board);

		//now we only have the last two ys left
		for (int x=0; x<w-2; x++) {
//			print(board);
			naiveMoveToXFirst(solved[x][h-1], x, h-1);
			if (solved[x][h-2]==board[x][h-2]) {
				locked[x][h-1] = locked[x][h-2]=true;
				continue;
			}
			locked[x][h-2] = true;
			naiveMoveToXFirst(solved[x][h-2], w-1, h-1);
			hardCW4(x, h-2);
			naiveMoveToXFirst(solved[x][h-2], x+1, h-2);
			hardCCW4(x, h-2);
			locked[x][h-1]=true;
		}

		//TODO: handle the last 4 spaces
		while (board[w-2][h-2]!=solved[w-2][h-2]) {
			hardCW4(w-2, h-2);
		}
		int target=solved[w-1][h-2];
		if (board[w-1][h-2]==target) {

		}
		else if (board[w-2][h-1]==target) {
			swapBottom2();
			swapRight2();
		}
		else {
			swapRight2();
		}
		target=solved[w-2][h-1];
		if (board[w-2][h-1]==target) {

		}
		else {
			swapBottom2();
		}
		System.out.println(answer.size());
		for (String s:answer) {
			System.out.println(s);
		}
//		print(board);
	}

	static void sixCycle() {
		hardCCW4(w-2, h-2);
		hardCCW4(w-3, h-2);
		moveNoWarnings(w-3, h-2, w-2, h-2, w-1, h-2,
				w-1, h-1, w-2, h-1, w-3, h-1);
	}

	static void swapRight2() {
		hardCCW4(w-2, h-2);
		sixCycle();
		hardCW4(w-2, h-2);
	}

	static void swapLeft2() {
		hardCW4(w-2, h-2);
		sixCycle();
		hardCCW4(w-2, h-2);
	}

	static void swaptTop2() {
		sixCycle();
	}

	static void swapBottom2() {
		hardCW4(w-2, h-2);
		hardCW4(w-2, h-2);
		sixCycle();
		hardCCW4(w-2, h-2);
		hardCCW4(w-2, h-2);
	}

	static boolean movable(int x, int y) {
		if (x< 0 || x>=locked.length || y<0 || y>=locked[x].length) return false;
		return !locked[x][y];
	}

	//moves x first then y
	static void naiveMoveToXFirst(int toMove, int targetX, int targetY) {
		Point curPos=locationOf(toMove);
		int curX=curPos.x;
		int curY=curPos.y;
		while (curX<targetX) {
			moveRight(curX, curY);
			curX++;
		}
		while (curX>targetX) {
			moveLeft(curX, curY);
			curX--;
		}
		while (curY<targetY) {
			moveDown(curX, curY);;
			curY++;
		}
		while (curY>targetY) {
			moveUp(curX, curY);
			curY--;
		}
	}

	static void moveLeft(int x, int y) {
		if (!movable(x, y) || !movable(x-1, y)) {
			throw null;
		}
		if (movable(x-1, y+1) && movable(x, y+1)) {
			move(x, y, x-1, y, x-1, y+1, x, y+1);
			return;
		}
		if (movable(x-1, y-1) && movable(x-1, y-1)) {
			move(x, y, x-1, y, x-1, y-1, x, y-1);
			return;
		}
		throw null;
	}

	static void moveRight(int x, int y) {
		if (!movable(x, y) || !movable(x+1, y)) {
			throw null;
		}
		if (movable(x+1, y+1) && movable(x, y+1)) {
			move(x, y, x+1, y, x+1, y+1, x, y+1);
			return;
		}
		if (movable(x+1, y-1) && movable(x, y-1)) {
			move(x, y, x+1, y, x+1, y-1, x, y-1);
			return;
		}
//		System.out.println("Trying to move right on pos: "+x+" "+y+" but it is impossible");
//		print(locked);
		throw null;
	}

	static void moveDown(int x, int y) {
		if (!movable(x, y) || !movable(x, y+1)) {
			throw null;
		}
		if (movable(x-1, y+1) && movable(x-1, y)) {
			move(x, y, x, y+1, x-1, y+1, x-1, y);
			return;
		}
		if (movable(x+1, y+1) && movable(x+1, y)) {
			move(x, y, x, y+1, x+1, y+1, x+1, y);
			return;
		}
		throw null;
	}

	static void moveUp(int x, int y) {
		if (!movable(x, y) || !movable(x, y-1)) {
			throw null;
		}
		if (movable(x-1, y-1) && movable(x-1, y)) {
			move(x, y, x, y-1, x-1, y-1, x-1, y);
			return;
		}
		if (movable(x+1, y-1) && movable(x+1, y)) {
			move(x, y, x, y-1, x+1, y-1, x+1, y);
			return;
		}
		throw null;
	}

	static void move(int ...input) {
		if (input.length%2!=0) throw null;
		int[] xs=new int[input.length/2], ys=new int[input.length/2];
		for (int i=0; i<input.length; i+=2) {
			xs[i/2]=input[i];
			ys[i/2]=input[i+1];
		}
		int nPoints=input.length/2;
		for (int i=0; i<nPoints; i++) {
			if (!movable(xs[i], ys[i])) throw null;
		}
		int[] old=new int[nPoints];
		for (int i=0; i<nPoints; i++) old[i]=board[xs[i]][ys[i]];
		for (int i=0; i<nPoints; i++) board[xs[i]][ys[i]] = old[(i-1+nPoints)%nPoints];
		StringBuilder sb=new StringBuilder(nPoints+" ");
		for (int i:old) {
			sb.append(i+" ");
		}
		answer.add(sb.toString());
	}

	static void moveNoWarnings(int ...input) {
		if (input.length%2!=0) throw null;
		int[] xs=new int[input.length/2], ys=new int[input.length/2];
		for (int i=0; i<input.length; i+=2) {
			xs[i/2]=input[i];
			ys[i/2]=input[i+1];
		}
		int nPoints=input.length/2;
		int[] old=new int[nPoints];
		for (int i=0; i<nPoints; i++) old[i]=board[xs[i]][ys[i]];
		for (int i=0; i<nPoints; i++) board[xs[i]][ys[i]] = old[(i-1+nPoints)%nPoints];
		StringBuilder sb=new StringBuilder(nPoints+" ");
		for (int i:old) {
			sb.append(i+" ");
		}
		answer.add(sb.toString());
	}

	static void hardCW4(int topLeftX, int topLeftY) {
		moveNoWarnings(topLeftX, topLeftY, topLeftX+1, topLeftY, topLeftX+1, topLeftY+1, topLeftX, topLeftY+1);
	}

	static void hardCCW4(int topLeftX, int topLeftY) {
		moveNoWarnings(topLeftX, topLeftY, topLeftX, topLeftY+1, topLeftX+1, topLeftY+1, topLeftX+1, topLeftY);
	}

	static Point locationOf(int i) {
		for(int x=0; x<w; x++) {
			for (int y=0; y<h; y++) {
				if (board[x][y]==i) return new Point(x, y);
			}
		}
//		System.out.println("Couldn't find location of "+i+" in ");
//		print(board);
		throw null;
	}

	static class FastScanner {
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st=new StringTokenizer("");
		String next() {
			while (!st.hasMoreElements()) {
				try {
					st=new StringTokenizer(br.readLine());
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			return st.nextToken();
		}

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

	static class Point {
		int x, y;
		public Point(int x, int y) {
			this.x=x;
			this.y=y;
		}
	}

	static void print(int[][] board) {
		for (int y=0; y<board[0].length; y++) {
			for (int x=0; x<board.length; x++) System.out.print(board[x][y]+" ");
			System.out.println();
		}
		System.out.println();
	}
	static void print(boolean[][] board) {
		for (int y=0; y<board[0].length; y++) {
			for (int x=0; x<board.length; x++) System.out.print((board[x][y]?"*":"_")+" ");
			System.out.println();
		}
		System.out.println();
	}
}


import java.io.*;
import java.util.ArrayList;
import java.util.HashSet;

public class xenodrome {

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

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

		String arr[]=br.readLine().split(" ");

		int n=Integer.parseInt(arr[0]);
		int m=Integer.parseInt(arr[1]);

		ArrayList<Integer> li=new ArrayList<>();

		while(n>0)
		{
			li.add(n%m);

			n=n/m;
		}

		HashSet<Integer> set=new HashSet<>();

		for(int i=0;i<li.size();i++)
		{
			set.add(li.get(i));
		}

		if(li.size()==set.size())
			System.out.println("YES");
		else
			System.out.println("NO");
	}

}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;
public class C {
    static class FastScanner {
        int idk;
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer("");

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

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

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

        long nextLong() {
            return Long.parseLong(next());
        }
    }
    static class FastWriter extends PrintWriter {
        FastWriter() {
            super(System.out);
        }

        void println(int[] array) {
            for (int i = 0; i < array.length; i++) {
                print(array[i] + " ");
            }
            println();
        }

        void println(long[] array) {
            long ans[]=new long[10];
            for (int i = 0; i < array.length; i++) {
                print(array[i] + " ");
            }
            println();
        }
    }
    public static void main(String[] args) {
        // Yo bitch !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        FastScanner in = new FastScanner();
        FastWriter out = new FastWriter();
        int n = in.nextInt();
        int m = in.nextInt();
        boolean[] used = new boolean[m];
        boolean valid = true;
        while (n > 0) {
            int d = n % m;
            if (used[d]) {
                valid = false;
                break;
            }
            used[d] = true;
            n /= m;
        }
        if(valid){
            out.println("YES");
        }else {
            out.println("NO");
        }
        out.close();
    }
}


import java.io.*;
import java.nio.CharBuffer;
import java.util.NoSuchElementException;

public class P1505D {

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

        int n = scanner.nextInt();
        int m = scanner.nextInt();
        boolean[] used = new boolean[m];
        boolean valid = true;
        while (n > 0) {
            int d = n % m;
            if (used[d]) {
                valid = false;
                break;
            }
            used[d] = true;
            n /= m;
        }
        writer.println(valid ? "YES" : "NO");

        writer.close();
    }

    private static class SimpleScanner {

        private static final int BUFFER_SIZE = 10240;

        private Readable in;
        private CharBuffer buffer;
        private boolean eof;

        private SimpleScanner(InputStream in) {
            this.in = new BufferedReader(new InputStreamReader(in));
            buffer = CharBuffer.allocate(BUFFER_SIZE);
            buffer.limit(0);
            eof = false;
        }

        private char read() {
            if (!buffer.hasRemaining()) {
                buffer.clear();
                int n;
                try {
                    n = in.read(buffer);
                } catch (IOException e) {
                    n = -1;
                }
                if (n <= 0) {
                    eof = true;
                    return '\0';
                }
                buffer.flip();
            }
            return buffer.get();
        }

        private void checkEof() {
            if (eof)
                throw new NoSuchElementException();
        }

        private char nextChar() {
            checkEof();
            char b = read();
            checkEof();
            return b;
        }

        private String next() {
            char b;
            do {
                b = read();
                checkEof();
            } while (Character.isWhitespace(b));
            StringBuilder sb = new StringBuilder();
            do {
                sb.append(b);
                b = read();
            } while (!eof && !Character.isWhitespace(b));
            return sb.toString();
        }

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

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

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


//https://codeforces.com/contest/1505/problem/D
//D. Xenolith? Hippodrome?
import java.util.*;
import java.io.*;
public class CF_1505_D{

	static boolean check(int n, int m){
		boolean pres[] = new boolean[m];

		while(n>0){
			int temp = n%m;

			if(pres[temp])
				return false;
			else
				pres[temp] = true;

			n = n/m;
		}
		return true;
	}

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

		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
		StringTokenizer st;

		st = new StringTokenizer(br.readLine().trim());
		int n = Integer.parseInt(st.nextToken());
		int m = Integer.parseInt(st.nextToken());

		boolean flag = check(n, m);

		if(flag)
			pw.print("YES");
		else
			pw.print("NO");

		pw.flush();
		pw.close();
	}
}


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

public class CF392E {

    final static int MINF = -1000000000;

    public static void solve(Input in, PrintWriter out) throws IOException {
        int n = in.nextInt();
        int[] ws = new int[n + 1];
        for (int i = 1; i <= n; ++i) {
            ws[i] = in.nextInt();
        }
        int[] a = new int[n];
        for (int i = 0; i < n; ++i) {
            a[i] = in.nextInt();
        }
        int[][] d0 = new int[n][n];
        int[][] d1 = new int[n][n];
        for (int[] ar : d1) {
            Arrays.fill(ar, MINF);
        }
        for (int len = 1; len <= n; ++len) {
            for (int i = 0; i < n; ++i) {
                if (len == 1) {
                    d1[i][i] = 0;
                } else {
                    if (i - len + 1 >= 0) {
                        int j = i - len + 1;
                        d1[i][j] = MINF;
                        for (int k = j + 1; k <= i; ++k) {
                            if (a[j] + 1 == a[k] && d1[i][k] != MINF && d0[j + 1][k - 1] != MINF) {
                                d1[i][j] = Math.max(d1[i][j], d1[i][k] + d0[j + 1][k - 1]);
                            }
                        }
                    }
                    if (i + len - 1 < n) {
                        int j = i + len - 1;
                        d1[i][j] = MINF;
                        for (int k = i; k < j; ++k) {
                            if (a[j] + 1 == a[k] && d1[i][k] != MINF && d0[k + 1][j - 1] != MINF) {
                                d1[i][j] = Math.max(d1[i][j], d1[i][k] + d0[k + 1][j - 1]);
                            }
                        }
                    }
                }
            }
            for (int i = 0; i + len <= n; ++i) {
                int j = i + len - 1;
                d0[i][j] = MINF;
                for (int k = i; k < j; ++k) {
                    d0[i][j] = Math.max(d0[i][j], d0[i][k] + d0[k + 1][j]);
                }
                for (int k = i; k <= j; ++k) {
                    if (d1[k][i] != MINF && d1[k][j] != MINF) {
                        d0[i][j] = Math.max(d0[i][j], d1[k][i] + d1[k][j] + ws[2 * a[k] - a[i] - a[j] + 1]);
                    }
                }
            }
        }
        out.println(d0[0][n - 1]);
    }

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

    static class Input {
        BufferedReader in;
        StringBuilder sb = new StringBuilder();

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

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

        public String next() throws IOException {
            sb.setLength(0);
            while (true) {
                int c = in.read();
                if (c == -1) {
                    return null;
                }
                if (" \n\r\t".indexOf(c) == -1) {
                    sb.append((char)c);
                    break;
                }
            }
            while (true) {
                int c = in.read();
                if (c == -1 || " \n\r\t".indexOf(c) != -1) {
                    break;
                }
                sb.append((char)c);
            }
            return sb.toString();
        }

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

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

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


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

public class CF392E {

    final static int MINF = -1000000000;

    public static void solve(Input in, PrintWriter out) throws IOException {
        int n = in.nextInt();
        int[] ws = new int[n + 1];
        for (int i = 1; i <= n; ++i) {
            ws[i] = in.nextInt();
        }
        int[] a = new int[n];
        for (int i = 0; i < n; ++i) {
            a[i] = in.nextInt();
        }
        int[][] d0 = new int[n][n];
        int[][] d1 = new int[n][n];
        for (int[] ar : d1) {
            Arrays.fill(ar, MINF);
        }
        for (int len = 1; len <= n; ++len) {
            for (int i = 0; i < n; ++i) {
                if (len == 1) {
                    d1[i][i] = 0;
                } else {
                    if (i - len + 1 >= 0) {
                        int j = i - len + 1;
                        d1[i][j] = MINF;
                        for (int k = j + 1; k <= i; ++k) {
                            if (a[j] + 1 == a[k] && d1[i][k] != MINF && d0[j + 1][k - 1] != MINF) {
                                d1[i][j] = Math.max(d1[i][j], d1[i][k] + d0[j + 1][k - 1]);
                            }
                        }
                    }
                    if (i + len - 1 < n) {
                        int j = i + len - 1;
                        d1[i][j] = MINF;
                        for (int k = i; k < j; ++k) {
                            if (a[j] + 1 == a[k] && d1[i][k] != MINF && d0[k + 1][j - 1] != MINF) {
                                d1[i][j] = Math.max(d1[i][j], d1[i][k] + d0[k + 1][j - 1]);
                            }
                        }
                    }
                }
            }
            for (int i = 0; i + len <= n; ++i) {
                int j = i + len - 1;
                d0[i][j] = MINF;
                for (int k = i; k < j; ++k) {
                    d0[i][j] = Math.max(d0[i][j], d0[i][k] + d0[k + 1][j]);
                }
                for (int k = i; k <= j; ++k) {
                    if (d1[k][i] != MINF && d1[k][j] != MINF) {
                        d0[i][j] = Math.max(d0[i][j], d1[k][i] + d1[k][j] + ws[2 * a[k] - a[i] - a[j] + 1]);
                    }
                }
            }
        }
        int[] d2 = new int[n + 1];
        d2[0] = 0;
        for (int i = 0; i < n; ++i) {
            d2[i + 1] = Math.max(d2[i + 1], d2[i]);
            for (int j = i; j < n; ++j) {
                d2[j + 1] = Math.max(d2[j + 1], d2[i] + d0[i][j]);
            }
        }
        out.println(d2[n]);
    }

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

    static class Input {
        BufferedReader in;
        StringBuilder sb = new StringBuilder();

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

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

        public String next() throws IOException {
            sb.setLength(0);
            while (true) {
                int c = in.read();
                if (c == -1) {
                    return null;
                }
                if (" \n\r\t".indexOf(c) == -1) {
                    sb.append((char)c);
                    break;
                }
            }
            while (true) {
                int c = in.read();
                if (c == -1 || " \n\r\t".indexOf(c) != -1) {
                    break;
                }
                sb.append((char)c);
            }
            return sb.toString();
        }

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

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

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


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

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

    static final class TaskF {
        private static final int MODULO = 1_000_000_000 + 7;
        private String subsequence;
        private int[][] nextPosition;
        private int[][][][] dp;

        public void solve(int __, InputReader in, PrintWriter out) {
            int maxBalance = in.nextInt();
            int length = 2 * maxBalance;
            subsequence = in.next();
            nextPosition = new int[subsequence.length() + 1][2];
            for (int i = 0; i <= subsequence.length(); ++i) {
                for (int type = 0; type < 2; ++type) {
                    char parenthesis = "()".charAt(type);
                    int k;
                    link:
                    for (k = Math.min(subsequence.length(), i + 1); k > 0; --k) {
                        if (subsequence.charAt(k - 1) != parenthesis) continue;
                        for (int j = k - 1; j-- > 0; ) {
                            if (subsequence.charAt(j) != subsequence.charAt(i - k + 1 + j)) {
                                continue link;
                            }
                        }
                        break;
                    }
                    nextPosition[i][type] = k;
                }
            }
            dp = new int[length + 1][maxBalance + 1][subsequence.length() + 1][2];
            dp[0][0][0][0] = 1;
            for (int len = 0; len < length; ++len) {
                for (int balance = 0; balance <= Math.min(len, maxBalance); ++balance) {
                    for (int pos = 0; pos <= Math.min(len, subsequence.length()); ++pos) {
                        for (int was = 0; was < 2; ++was) {
                            if (dp[len][balance][pos][was] == 0) continue;
                            if (balance < maxBalance) {
                                update(len, balance, pos, was, '(');
                            }
                            if (balance > 0) {
                                update(len, balance, pos, was, ')');
                            }
                        }
                    }
                }
            }
            int sum = 0;
            for (int pos = 0; pos <= subsequence.length(); ++pos) {
                sum = sum(sum, dp[length][0][pos][1]);
            }
            out.println(sum);
        }

        private void update(int len, int balance, int pos, int was, char parenthesis) {
            int nextLen = len + 1;
            int nextBalance = balance + (parenthesis == '(' ? 1 : -1);
            int nextPos = nextPosition[pos]["()".indexOf(parenthesis)];
            int nextWas = was | (nextPos == subsequence.length() ? 1 : 0);
            dp[nextLen][nextBalance][nextPos][nextWas] =
                    sum(dp[nextLen][nextBalance][nextPos][nextWas], dp[len][balance][pos][was]);
        }

        private int sum(int first, int second) {
            return (first + second) % MODULO;
        }

    }

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

        public InputReader(InputStream in) {
            reader = new BufferedReader(new InputStreamReader(in));
        }

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

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                tokenizer = new StringTokenizer(readLine());
            }
            return tokenizer.nextToken();
        }

        public String readLine() {
            String line;
            try {
                line = reader.readLine();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            return line;
        }

    }
}


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

public class Main {

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

        new Main().go();
    }

    PrintWriter out;
    Reader in;
    BufferedReader br;

    Main() throws IOException {

        try {

            //br = new BufferedReader( new FileReader("input.txt") );
            //in = new Reader("input.txt");
            in = new Reader("input.txt");
            out = new PrintWriter( new BufferedWriter(new FileWriter("output.txt")) );
        }
        catch (Exception e) {

            //br = new BufferedReader( new InputStreamReader( System.in ) );
            in = new Reader();
            out = new PrintWriter( new BufferedWriter(new OutputStreamWriter(System.out)) );
        }
    }

    void go() throws Exception {

        //int t = in.nextInt();
        int t = 1;
        while (t > 0) {
            solve();
            t--;
        }

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

    int inf = 2000000000;
    int mod = 1000000007;
    double eps = 0.000000001;

    int n;
    int m;

    ArrayList<Pair>[] g;
    String s;
    int[] maxPref = new int[200];
    void solve() throws IOException {
        n = in.nextInt();
        s = in.nextLine();

        StringBuilder sb = new StringBuilder();
        sb.append(s.charAt(0));
        for (int i = 1; i < s.length(); i++) {
            char br = '(';
            if (s.charAt(i) == '(') br = ')';
            String t = sb.toString() + br;
            for (int j = 1; j < t.length(); j++) {
                boolean ok = true;
                int pos = 0;
                for (int k = j; k < t.length(); k++) {
                    ok &= s.charAt(pos) == t.charAt(k);
                    pos++;
                }
                if (ok) {
                    maxPref[i] = t.length() - j;
                    break;
                }
            }
            sb.append(s.charAt(i));
        }

        out.println(f(0, 0,0));
    }

    int cnt(int start, String sub, int n) {
        int[][] dp = new int[n][n];
        boolean[][] used = new boolean[n][n];
        for (int i = 0; i < n; i++) {
            boolean any = i < start || i >= start + sub.length();
            for (int j = 0; j <= n / 2; j++) {
                if (i == 0) {
                    if (any || sub.charAt(0) == '(') {
                        dp[0][1] = 1;
                        used[0][1] = true;
                    }
                    continue;
                }

                if (any || sub.charAt(i - start) == '(') {
                    if (used[i - 1][j]) {
                        dp[i][j + 1] = (dp[i][j + 1] + dp[i - 1][j]) % mod;
                        used[i][j + 1] = true;
                    }
                }

                if (any || sub.charAt(i - start) == ')') {
                    if (j > 0 && used[i - 1][j]) {
                        dp[i][j - 1] = (dp[i][j - 1] + dp[i - 1][j]) % mod;
                        used[i][j - 1] = true;
                    }
                }
            }
        }
        return dp[n - 1][0];
    }

    int[][][] dp = new int[200][101][201];
    boolean[][][] used = new boolean[200][101][201];
    int f(int pos, int balance, int pref) {

        if (balance < 0 || balance > n)
            return 0;

        if (pos == n * 2) {
            return balance == 0 && pref == s.length() ? 1 : 0;
        }

        if (used[pos][balance][pref])
            return dp[pos][balance][pref];

        int res = 0;
        if (pref == s.length()) {
            res = f(pos + 1, balance + 1, pref)
                    + f(pos + 1, balance - 1, pref);
        } else {
            if (s.charAt(pref) == '(') {
                res += f(pos + 1, balance + 1, pref + 1);
                res += f(pos + 1, balance - 1, maxPref[pref]);
            }
            else {
                res += f(pos + 1, balance - 1, pref + 1);
                res += f(pos + 1, balance + 1, maxPref[pref]);
            }
        }

        dp[pos][balance][pref] = res % mod;
        used[pos][balance][pref] = true;
        return dp[pos][balance][pref];
    }

    class Pair implements Comparable<Pair>{

        int a;
        int b;

        Pair(int a, int b) {

            this.a = a;
            this.b = b;
        }

        public int compareTo(Pair p) {
            if (a != p.a)
                return Integer.compare(a, p.a);
            else
                return Integer.compare(b, p.b);
        }
    }

    class Item {

        int a;
        int b;
        int c;

        Item(int a, int b, int c) {
            this.a = a;
            this.b = b;
            this.c = c;
        }

    }

    class Reader {

        BufferedReader  br;
        StringTokenizer tok;

        Reader(String file) throws IOException {
            br = new BufferedReader( new FileReader(file) );
        }

        Reader() throws IOException {
            br = new BufferedReader( new InputStreamReader(System.in) );
        }

        String next() throws IOException {

            while (tok == null || !tok.hasMoreElements())
                tok = new StringTokenizer(br.readLine());
            return tok.nextToken();
        }

        int nextInt() throws NumberFormatException, IOException {
            return Integer.valueOf(next());
        }

        long nextLong() throws NumberFormatException, IOException {
            return Long.valueOf(next());
        }

        double nextDouble() throws NumberFormatException, IOException {
            return Double.valueOf(next());
        }

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

    }

    static class InputReader
    {
        final private int BUFFER_SIZE = 1 << 16;
        private DataInputStream din;
        private byte[] buffer;
        private int bufferPointer, bytesRead;

        public InputReader()
        {
            din = new DataInputStream(System.in);
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public InputReader(String file_name) throws IOException
        {
            din = new DataInputStream(new FileInputStream(file_name));
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public String readLine() throws IOException
        {
            byte[] buf = new byte[64]; // line length
            int cnt = 0, c;
            while ((c = read()) != -1)
            {
                if (c == '\n')
                    break;
                buf[cnt++] = (byte) c;
            }
            return new String(buf, 0, cnt);
        }

        public int nextInt() throws IOException
        {
            int ret = 0;
            byte c = read();
            while (c <= ' ')
                c = read();
            boolean neg = (c == '-');
            if (neg)
                c = read();
            do
            {
                ret = ret * 10 + c - '0';
            }  while ((c = read()) >= '0' && c <= '9');

            if (neg)
                return -ret;
            return ret;
        }

        public long nextLong() throws IOException
        {
            long ret = 0;
            byte c = read();
            while (c <= ' ')
                c = read();
            boolean neg = (c == '-');
            if (neg)
                c = read();
            do {
                ret = ret * 10 + c - '0';
            }
            while ((c = read()) >= '0' && c <= '9');
            if (neg)
                return -ret;
            return ret;
        }

        public double nextDouble() throws IOException
        {
            double ret = 0, div = 1;
            byte c = read();
            while (c <= ' ')
                c = read();
            boolean neg = (c == '-');
            if (neg)
                c = read();

            do {
                ret = ret * 10 + c - '0';
            }
            while ((c = read()) >= '0' && c <= '9');

            if (c == '.')
            {
                while ((c = read()) >= '0' && c <= '9')
                {
                    ret += (c - '0') / (div *= 10);
                }
            }

            if (neg)
                return -ret;
            return ret;
        }

        private void fillBuffer() throws IOException
        {
            bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
            if (bytesRead == -1)
                buffer[0] = -1;
        }

        private byte read() throws IOException
        {
            if (bufferPointer == bytesRead)
                fillBuffer();
            return buffer[bufferPointer++];
        }

        public void close() throws IOException
        {
            if (din == null)
                return;
            din.close();
        }
    }

}


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

public class BracketSubstring_CF1015F {

	static String s;
	static int len;
	static int sub;

	static int memo[][][][];
	static final int MOD = (int)1e9 + 7;

	static int fail[];
	static char[] pat;
	static void pattern(){
		int len= pat.length;
		fail= new int [len];
		fail[0]=0;
		int k=0;
		for(int i=1; i<len; i++){
			while(k>0 && pat[i]!=pat[k])
				k= fail[k-1];

			if(pat[i]==pat[k])
				fail[i]=++k;
			else fail[i]=k;
		}
	}

	static int dp(int i, int count, int commpr, int used){

		if(i == len){
			return count == 0 && used == 1 ? 1 : 0;
		}

		if(count < 0)
			return 0;

		if(memo[i][count][commpr][used] != -1){
			return memo[i][count][commpr][used];
		}
		int commpr1 = commpr;
		while(commpr1>0 && pat[commpr1]!='(')
			commpr1 = fail[commpr1 - 1];

		int newused1 = used;

		if(pat[commpr1]=='(')
			commpr1++;
		if(commpr1 == sub){
			newused1 = 1;
			commpr1 = 0;

		}
		int commpr2 = commpr;
		int newused2 = used;
		while(commpr2>0 && pat[commpr2]!=')')
			commpr2 = fail[commpr2 - 1];

		if(pat[commpr2]==')')
			commpr2++;
		if(commpr2 == sub){
			newused2 = 1;
			commpr2 = 0;
		}

		int result = dp(i + 1, count + 1, commpr1 , newused1);
		result +=	 dp(i + 1, count - 1, commpr2 , newused2);

		return memo[i][count][commpr][used] = result % MOD;

	}

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

		Scanner sc = new Scanner(System.in);
		PrintWriter out = new PrintWriter(System.out);
		len = 2 * sc.nextInt();
		s = sc.next();
		sub = s.length();
		pat = s.toCharArray();
		memo = new int [len][len][sub][2];
		pattern();
		for(int i = 0; i < len; i++){
			for(int j = 0; j < len; j++){
				for(int k = 0; k < sub; k++)
				Arrays.fill(memo[i][j][k], -1);
			}
		}
		out.println(dp(0,0,0,0));
		out.flush();
		out.close();
	}

	static class Scanner {
		StringTokenizer st;
		BufferedReader br;

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

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

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

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

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

		public double nextDouble() throws IOException {
			String x = next();
			StringBuilder sb = new StringBuilder("0");
			double res = 0, f = 1;
			boolean dec = false, neg = false;
			int start = 0;
			if (x.charAt(0) == '-') {
				neg = true;
				start++;
			}
			for (int i = start; i < x.length(); i++)
				if (x.charAt(i) == '.') {
					res = Long.parseLong(sb.toString());
					sb = new StringBuilder("0");
					dec = true;
				} else {
					sb.append(x.charAt(i));
					if (dec)
						f *= 10;
				}
			res += Long.parseLong(sb.toString()) / f;
			return res * (neg ? -1 : 1);
		}

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

	}

}