import java.io.*;
import java.math.*;
import java.util.*;
import java.util.stream.*;

public class BOI2020C {

	static class StackDSU {
		int[] p;

		int[] idxH;
		int[] valH;
		int time = 0;

		int[] snap;
		int snapSz;

		public StackDSU(int n, int maxStackSize, int histSize) {
			p = new int[n];
			Arrays.fill(p, -1);
			idxH = new int[histSize];
			valH = new int[histSize];
			snap = new int[maxStackSize + 1];
		}

		int get(int v) {
			int ret = 0;
			while (p[v] >= 0) {
				ret ^= p[v];
				v = p[v] >> 1;
			}
			return (v << 1) | (ret & 1);
		}

		boolean canAdd(int v, int u) {
			v = get(v);
			u = get(u);

			int diff = (v ^ u) & 1;
			return ((v >> 1) != (u >> 1)) || (diff == 1);
		}

		void unite(int v, int u) {
			v = get(v);
			u = get(u);

			int diff = (v ^ u) & 1;
			v >>= 1;
			u >>= 1;

			if (v == u) {
				if (diff == 0) {
					throw new AssertionError();
				}
				return;
			}
			if (p[v] < p[u]) {
				int tmp = v;
				v = u;
				u = tmp;
			}
			set(u, p[v] + p[u]);
			set(v, (u << 1) | (diff ^ 1));
			return;
		}

		void set(int idx, int val) {
			if (p[idx] != val) {
				idxH[time] = idx;
				valH[time] = p[idx];
				p[idx] = val;
				++time;
			}
		}

		public void push(UpdateInfo upd) {
			snap[snapSz++] = time;
			unite(upd.u, upd.v);
		}

		public void pop() {
			int rollTo = snap[--snapSz];
			while (time > rollTo) {
				--time;
				p[idxH[time]] = valH[time];
			}
		}
	}

	// Must have auto-incrementable ID.
	static class UpdateInfo {
		private static int count;
		int id;

		int v, u;

		public UpdateInfo(int v, int u) {
			id = count++;
			this.v = v;
			this.u = u;
		}
	}

	static class QueueFromStack {
		public StackDSU ds;

		// stack of updates that shows in which order they were actually applied
		private UpdateInfo[] stack;
		private int size;

		private UpdateInfo[] buf;

		// updates with id < mark are grouped into power-of-2 length blocks
		// and are in the "correct"(i.e. reversed) order
		private int mark;

		// id of queue's head or mark if queue is empty
		private int head;

		public QueueFromStack(StackDSU ds, int maxQueueSize) {
			UpdateInfo.count = 0;
			this.ds = ds;
			stack = new UpdateInfo[maxQueueSize];
			buf = new UpdateInfo[maxQueueSize];
		}

		public void add(UpdateInfo upd) {
			stack[size++] = upd;
			ds.push(upd);
		}

		public void poll() {
			if (mark == head) {
				mark = UpdateInfo.count;
				for (int i = size - 1; i >= 0; --i) {
					ds.pop();
					buf[i] = stack[i];
				}
				for (int i = 0; i < size; ++i) {
					ds.push(stack[i] = buf[size - 1 - i]);
				}
			}
			int ptr = 0;
			while (stack[size - 1].id != head) {
				// must have id >= mark
				buf[ptr++] = stack[--size];
				ds.pop();
			}

			if (ptr == 0) {
				ds.pop();
				--size;
				++head;
				return;
			}

			int skip = ptr;
			int chunk = Integer.lowestOneBit(mark - head);
			for (int i = 0; i < chunk; ++i) {
				// must have id < mark
				buf[ptr++] = stack[--size];
				ds.pop();
			}

			// putting back id >= mark
			for (int i = skip - 1; i >= 0; --i) {
				ds.push(stack[size++] = buf[i]);
			}
			// putting back id < mark except id == head
			for (int i = ptr - 1; i > skip; --i) {
				ds.push(stack[size++] = buf[i]);
			}

			++head;
		}
	}

	boolean[] fast(int n, int[] vs, int[] us, int[] ls, int[] rs) {
		int m = vs.length;
		int q = ls.length;

		StackDSU dsu = new StackDSU(n, 2 * m, 2_000_000);
		QueueFromStack que = new QueueFromStack(dsu, 2 * m);

		int[] stop = new int[m];

		for (int i = 0, j = 0; i < m; i++) {
			while (j < 2 * m) {
				int v = vs[j % m];
				int u = us[j % m];
				if (!dsu.canAdd(v, u)) {
					break;
				}
				que.add(new UpdateInfo(v, u));
				++j;
			}
			stop[i] = j;
			que.poll();
		}

		boolean[] ret = new boolean[q];

		for (int i = 0; i < q; i++) {
			int l = ls[i];
			int r = rs[i];
			boolean ans;
			if (r == m - 1) {
				ans = stop[0] < l;
			} else {
				ans = stop[r + 1] < l + m;
			}
			ret[i] = ans;
		}

		return ret;
	}

	static boolean test(int mask, int i) {
		return ((mask >> i) & 1) == 1;
	}

	boolean slowSingle(int n, int[] vs, int[] us, int l, int r) {
		outer: for (int mask = 0; mask < 1 << n; mask++) {
			for (int i = 0; i < vs.length; i++) {
				if (l <= i && i <= r) {
					continue;
				}
				if (test(mask, vs[i]) == test(mask, us[i])) {
					continue outer;
				}
			}
			return false;
		}
		return true;
	}

	boolean[] slow(int n, int[] vs, int[] us, int[] ls, int[] rs) {
		boolean[] ret = new boolean[ls.length];

		for (int i = 0; i < ls.length; i++) {
			ret[i] = slowSingle(n, vs, us, ls[i], rs[i]);
		}

		return ret;
	}

	void submit() {
		int n = nextInt();
		int m = nextInt();
		int q = nextInt();
		int[] vs = new int[m];
		int[] us = new int[m];
		for (int i = 0; i < m; i++) {
			vs[i] = nextInt() - 1;
			us[i] = nextInt() - 1;
		}

		int[] ls = new int[q];
		int[] rs = new int[q];

		for (int i = 0; i < q; i++) {
			ls[i] = nextInt() - 1;
			rs[i] = nextInt() - 1;
		}

		boolean[] ans = fast(n, vs, us, ls, rs);
//		boolean[] ans = slow(n, vs, us, ls, rs);

		for (boolean b : ans) {
			out.println(b ? "YES" : "NO");
		}
	}

	void test() {

	}

	static final int B = 10;

	void stress() {
		for (int tst = 0;; tst++) {
			int n = rand(2, B);
			int m = rand(1, B);
			int q = B;
			int[] vs = new int[m];
			int[] us = new int[m];
			for (int i = 0; i < m; i++) {
				vs[i] = rand(0, n - 1);
				us[i] = (vs[i] + rand(1, n - 1)) % n;
			}
			int[] ls = new int[q];
			int[] rs = new int[q];
			for (int i = 0; i < q; i++) {
				ls[i] = rand(0, m - 1);
				rs[i] = rand(ls[i], m - 1);
			}

			boolean[] fast = fast(n, vs, us, ls, rs);
			boolean[] slow = slow(n, vs, us, ls, rs);

			if (!Arrays.equals(fast, slow)) {
				System.err.println(n + " " + m + " " + q);
				System.err.println(Arrays.toString(vs));
				System.err.println(Arrays.toString(us));
				System.err.println(Arrays.toString(ls));
				System.err.println(Arrays.toString(rs));

				System.err.println("fast " + Arrays.toString(fast));
				System.err.println("slow " + Arrays.toString(slow));
				throw new AssertionError();
			}
			System.err.println(tst);
		}
	}

	BOI2020C() throws IOException {
		is = System.in;
		out = new PrintWriter(System.out);
		submit();
//		 stress();
		// test();
		out.close();
	}

	static final Random rng = new Random();
	static final int C = 5;

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

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

	private InputStream is;
	PrintWriter out;

	private byte[] buf = new byte[1 << 14];
	private int bufSz = 0, bufPtr = 0;

	private int readByte() {
		if (bufSz == -1)
			throw new RuntimeException("Reading past EOF");
		if (bufPtr >= bufSz) {
			bufPtr = 0;
			try {
				bufSz = is.read(buf);
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
			if (bufSz <= 0)
				return -1;
		}
		return buf[bufPtr++];
	}

	private boolean isTrash(int c) {
		return c < 33 || c > 126;
	}

	private int skip() {
		int b;
		while ((b = readByte()) != -1 && isTrash(b))
			;
		return b;
	}

	String nextToken() {
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while (!isTrash(b)) {
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	String nextString() {
		int b = readByte();
		StringBuilder sb = new StringBuilder();
		while (!isTrash(b) || b == ' ') {
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

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

	char nextChar() {
		return (char) skip();
	}

	int nextInt() {
		int ret = 0;
		int b = skip();
		if (b != '-' && (b < '0' || b > '9')) {
			throw new InputMismatchException();
		}
		boolean neg = false;
		if (b == '-') {
			neg = true;
			b = readByte();
		}
		while (true) {
			if (b >= '0' && b <= '9') {
				ret = ret * 10 + (b - '0');
			} else {
				if (b != -1 && !isTrash(b)) {
					throw new InputMismatchException();
				}
				return neg ? -ret : ret;
			}
			b = readByte();
		}
	}

	long nextLong() {
		long ret = 0;
		int b = skip();
		if (b != '-' && (b < '0' || b > '9')) {
			throw new InputMismatchException();
		}
		boolean neg = false;
		if (b == '-') {
			neg = true;
			b = readByte();
		}
		while (true) {
			if (b >= '0' && b <= '9') {
				ret = ret * 10 + (b - '0');
			} else {
				if (b != -1 && !isTrash(b)) {
					throw new InputMismatchException();
				}
				return neg ? -ret : ret;
			}
			b = readByte();
		}
	}
}


import java.io.*;
import java.math.*;
import java.util.*;
import java.util.stream.*;

public class BOI2020C {

	static class StackDSU {
		int[] p;

		int[] idxH;
		int[] valH;
		int time = 0;

		int[] snap;
		int snapSz;

		public StackDSU(int n, int maxStackSize, int histSize) {
			p = new int[n];
			Arrays.fill(p, -1);
			idxH = new int[histSize];
			valH = new int[histSize];
			snap = new int[maxStackSize + 1];
		}

		int get(int v) {
			int ret = 0;
			while (p[v] >= 0) {
				ret ^= p[v];
				v = p[v] >> 1;
			}
			return (v << 1) | (ret & 1);
		}

		boolean canAdd(int v, int u) {
			v = get(v);
			u = get(u);

			int diff = (v ^ u) & 1;
			return ((v >> 1) != (u >> 1)) || (diff == 1);
		}

		void unite(int v, int u) {
			v = get(v);
			u = get(u);

			int diff = (v ^ u) & 1;
			v >>= 1;
			u >>= 1;

			if (v == u) {
				if (diff == 0) {
					throw new AssertionError();
				}
				return;
			}
			if (p[v] < p[u]) {
				int tmp = v;
				v = u;
				u = tmp;
			}
			set(u, p[v] + p[u]);
			set(v, (u << 1) | (diff ^ 1));
			return;
		}

		void set(int idx, int val) {
			if (p[idx] != val) {
				idxH[time] = idx;
				valH[time] = p[idx];
				p[idx] = val;
				++time;
			}
		}

		public void push(UpdateInfo upd) {
			snap[snapSz++] = time;
			unite(upd.u, upd.v);
		}

		public void pop() {
			int rollTo = snap[--snapSz];
			while (time > rollTo) {
				--time;
				p[idxH[time]] = valH[time];
			}
		}
	}

	// Must have auto-incrementable ID.
	static class UpdateInfo {
		private static int count;
		int id;

		int v, u;

		public UpdateInfo(int v, int u) {
			id = count++;
			this.v = v;
			this.u = u;
		}
	}

	static class QueueFromStack {
		public StackDSU ds;

		// stack of updates that shows in which order they were actually applied
		private UpdateInfo[] stack;
		private int size;

		private UpdateInfo[] buf;

		// updates with id < mark are grouped into power-of-2 length blocks
		// and are in the "correct"(i.e. reversed) order
		private int mark;

		// id of queue's head or mark if queue is empty
		private int head;

		public QueueFromStack(StackDSU ds, int maxQueueSize) {
			UpdateInfo.count = 0;
			this.ds = ds;
			stack = new UpdateInfo[maxQueueSize];
			buf = new UpdateInfo[maxQueueSize];
		}

		public void add(UpdateInfo upd) {
			stack[size++] = upd;
			ds.push(upd);
		}

		public void poll() {
			if (mark == head) {
				mark = UpdateInfo.count;
				for (int i = size - 1; i >= 0; --i) {
					ds.pop();
					buf[i] = stack[i];
				}
				for (int i = 0; i < size; ++i) {
					ds.push(stack[i] = buf[size - 1 - i]);
				}
			}
			int ptr = 0;
			while (stack[size - 1].id != head) {
				// must have id >= mark
				buf[ptr++] = stack[--size];
				ds.pop();
			}

			if (ptr == 0) {
				ds.pop();
				--size;
				++head;
				return;
			}

			int skip = ptr;
			int chunk = Integer.lowestOneBit(mark - head);
			for (int i = 0; i < chunk; ++i) {
				// must have id < mark
				buf[ptr++] = stack[--size];
				ds.pop();
			}

			// putting back id >= mark
			for (int i = skip - 1; i >= 0; --i) {
				ds.push(stack[size++] = buf[i]);
			}
			// putting back id < mark except id == head
			for (int i = ptr - 1; i > skip; --i) {
				ds.push(stack[size++] = buf[i]);
			}

			++head;
		}
	}

	boolean[] fast(int n, int[] vs, int[] us, int[] ls, int[] rs) {
		int m = vs.length;
		int q = ls.length;

		StackDSU dsu = new StackDSU(n, 2 * m, 2_000_000);
		QueueFromStack que = new QueueFromStack(dsu, 2 * m);

		int[] stop = new int[m];

		for (int i = 0, j = 0; i < m; i++) {
			while (j < i + m) {
				int v = vs[j % m];
				int u = us[j % m];
				if (!dsu.canAdd(v, u)) {
					break;
				}
				que.add(new UpdateInfo(v, u));
				++j;
			}
			stop[i] = j;
			que.poll();
		}

		boolean[] ret = new boolean[q];

		for (int i = 0; i < q; i++) {
			int l = ls[i];
			int r = rs[i];
			boolean ans;
			if (r == m - 1) {
				ans = stop[0] < l;
			} else {
				ans = stop[r + 1] < l + m;
			}
			ret[i] = ans;
		}

		return ret;
	}

	static boolean test(int mask, int i) {
		return ((mask >> i) & 1) == 1;
	}

	boolean slowSingle(int n, int[] vs, int[] us, int l, int r) {
		outer: for (int mask = 0; mask < 1 << n; mask++) {
			for (int i = 0; i < vs.length; i++) {
				if (l <= i && i <= r) {
					continue;
				}
				if (test(mask, vs[i]) == test(mask, us[i])) {
					continue outer;
				}
			}
			return false;
		}
		return true;
	}

	boolean[] slow(int n, int[] vs, int[] us, int[] ls, int[] rs) {
		boolean[] ret = new boolean[ls.length];

		for (int i = 0; i < ls.length; i++) {
			ret[i] = slowSingle(n, vs, us, ls[i], rs[i]);
		}

		return ret;
	}

	void submit() {
		int n = nextInt();
		int m = nextInt();
		int q = nextInt();
		int[] vs = new int[m];
		int[] us = new int[m];
		for (int i = 0; i < m; i++) {
			vs[i] = nextInt() - 1;
			us[i] = nextInt() - 1;
		}

		int[] ls = new int[q];
		int[] rs = new int[q];

		for (int i = 0; i < q; i++) {
			ls[i] = nextInt() - 1;
			rs[i] = nextInt() - 1;
		}

		boolean[] ans = fast(n, vs, us, ls, rs);
//		boolean[] ans = slow(n, vs, us, ls, rs);

		for (boolean b : ans) {
			out.println(b ? "YES" : "NO");
		}
	}

	void test() {

	}

	static final int B = 10;

	void stress() {
		for (int tst = 0;; tst++) {
			int n = rand(2, B);
			int m = rand(1, B);
			int q = B;
			int[] vs = new int[m];
			int[] us = new int[m];
			for (int i = 0; i < m; i++) {
				vs[i] = rand(0, n - 1);
				us[i] = (vs[i] + rand(1, n - 1)) % n;
			}
			int[] ls = new int[q];
			int[] rs = new int[q];
			for (int i = 0; i < q; i++) {
				ls[i] = rand(0, m - 1);
				rs[i] = rand(ls[i], m - 1);
			}

			boolean[] fast = fast(n, vs, us, ls, rs);
			boolean[] slow = slow(n, vs, us, ls, rs);

			if (!Arrays.equals(fast, slow)) {
				System.err.println(n + " " + m + " " + q);
				System.err.println(Arrays.toString(vs));
				System.err.println(Arrays.toString(us));
				System.err.println(Arrays.toString(ls));
				System.err.println(Arrays.toString(rs));

				System.err.println("fast " + Arrays.toString(fast));
				System.err.println("slow " + Arrays.toString(slow));
				throw new AssertionError();
			}
			System.err.println(tst);
		}
	}

	BOI2020C() throws IOException {
		is = System.in;
		out = new PrintWriter(System.out);
		submit();
//		 stress();
		// test();
		out.close();
	}

	static final Random rng = new Random();
	static final int C = 5;

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

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

	private InputStream is;
	PrintWriter out;

	private byte[] buf = new byte[1 << 14];
	private int bufSz = 0, bufPtr = 0;

	private int readByte() {
		if (bufSz == -1)
			throw new RuntimeException("Reading past EOF");
		if (bufPtr >= bufSz) {
			bufPtr = 0;
			try {
				bufSz = is.read(buf);
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
			if (bufSz <= 0)
				return -1;
		}
		return buf[bufPtr++];
	}

	private boolean isTrash(int c) {
		return c < 33 || c > 126;
	}

	private int skip() {
		int b;
		while ((b = readByte()) != -1 && isTrash(b))
			;
		return b;
	}

	String nextToken() {
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while (!isTrash(b)) {
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	String nextString() {
		int b = readByte();
		StringBuilder sb = new StringBuilder();
		while (!isTrash(b) || b == ' ') {
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

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

	char nextChar() {
		return (char) skip();
	}

	int nextInt() {
		int ret = 0;
		int b = skip();
		if (b != '-' && (b < '0' || b > '9')) {
			throw new InputMismatchException();
		}
		boolean neg = false;
		if (b == '-') {
			neg = true;
			b = readByte();
		}
		while (true) {
			if (b >= '0' && b <= '9') {
				ret = ret * 10 + (b - '0');
			} else {
				if (b != -1 && !isTrash(b)) {
					throw new InputMismatchException();
				}
				return neg ? -ret : ret;
			}
			b = readByte();
		}
	}

	long nextLong() {
		long ret = 0;
		int b = skip();
		if (b != '-' && (b < '0' || b > '9')) {
			throw new InputMismatchException();
		}
		boolean neg = false;
		if (b == '-') {
			neg = true;
			b = readByte();
		}
		while (true) {
			if (b >= '0' && b <= '9') {
				ret = ret * 10 + (b - '0');
			} else {
				if (b != -1 && !isTrash(b)) {
					throw new InputMismatchException();
				}
				return neg ? -ret : ret;
			}
			b = readByte();
		}
	}
}


import java.io.*;

/**
 * Created by dalt on 2018/4/2.
 */
public class CF954H {
    public static final int MOD = (int) (1e9 + 7);
    public static BlockReader input;
    public static PrintStream output;

    public static void main(String[] args) throws FileNotFoundException {
        if (System.getProperty("ONLINE_JUDGE") == null) {
            input = new BlockReader(new FileInputStream("D:\\DataBase\\TESTCASE\\codeforces\\CF954H.in"));
            output = System.out;
        } else {
            input = new BlockReader(System.in);
            output = new PrintStream(new BufferedOutputStream(System.out), false);
        }

        solve();

        output.flush();
    }

    public static void solve() {
        int n = input.nextInteger();
        long[] a = new long[n];
        long[] aRev = new long[n];
        long[] aChoose2Child = new long[n + 1];
        long[] aChoose2ChildRev = new long[n + 1];
        long negTwo = pow(2, MOD - 2);
        for (int i = 0, until = n - 1; i < until; i++) {
            a[i] = input.nextInteger();
            aRev[i] = pow(a[i], MOD - 2);
        }

        for (int i = 0; i < n; i++) {
            aChoose2Child[i] = a[i] * (a[i] - 1) % MOD;
            aChoose2ChildRev[i] = pow( aChoose2Child[i], MOD - 2);
        }

        long[] prefixMul = new long[n];
        long[] prefixRev = new long[n];
        prefixMul[0] = 1;
        prefixRev[0] = 1;
        for (int i = 1; i < n; i++) {
            prefixMul[i] = prefixMul[i - 1] * a[i - 1] % MOD;
            prefixRev[i] = prefixRev[i - 1] * aRev[i - 1] % MOD;
        }

        int m = (n - 1) * 2;
        long[] f = new long[m + 1];
        Loop<long[][]> dpLoop = new Loop<>(new long[m + 1][3], new long[m + 1][3]);
        final int ROTATE = 0;
        final int BALANCE = 2;
        final int LINE = 1;

        {
            long[][] next = dpLoop.turn();
            next[0][BALANCE] = 1;
        }
        for (int i = n - 2; i >= 0; i--) {
            long[][] former = dpLoop.get(0);
            long[][] next = dpLoop.turn();

            long aChooseRev = aChoose2ChildRev[i + 1] * a[i + 1] % MOD * a[i + 1] % MOD * aChoose2Child[i] % MOD;
            for (int j = 2, until = ((n - 1) - i) * 2; j <= until; j++) {
                next[j][ROTATE] = (former[j - 2][ROTATE] * aChooseRev % MOD + former[j - 2][LINE] * aChoose2Child[i] % MOD) % MOD;

                int halfJ = j >> 1;
                if ((j & 1) == 0 && i + halfJ < n) {
                    long possible = prefixMul[i + halfJ] * prefixRev[i + 1] % MOD;
                    possible = possible * possible % MOD;
                    next[j][BALANCE] = possible * aChoose2Child[i]  % MOD * negTwo % MOD;
                } else {
                    next[j][BALANCE] = 0;
                }

                if (i + j < n) {
                    next[j][LINE] = prefixMul[i + j] * prefixRev[i] % MOD;
                } else {
                    next[j][LINE] = 0;
                }
            }

            next[2][BALANCE] = aChoose2Child[i] * negTwo % MOD;
            next[1][LINE] = a[i];
            next[0][BALANCE] = 1;

            for (int j = 1; j <= m; j++) {
                f[j] = (f[j] + (next[j][LINE] + next[j][ROTATE] + next[j][BALANCE]) * prefixMul[i]) % MOD;
            }
        }

        for (int i = 1; i <= m; i++) {
            output.print(f[i]);
            output.print(' ');
        }
    }

    public static long pow(long x, int n) {
        int bit = 31 - Integer.numberOfLeadingZeros(n);
        long product = 1;
        for (; bit >= 0; bit--) {
            product = product * product % MOD;
            if (((1 << bit) & n) != 0) {
                product = product * x % MOD;
            }
        }
        return product;
    }

    public static class Loop<T> {
        T[] data;
        int offset;

        public Loop(T... data) {
            this.data = data;
        }

        public T turn() {
            offset++;
            return get(0);
        }

        public T get(int index) {
            return data[(index + offset) % data.length];
        }
    }

    public static class BlockReader {
        static final int EOF = -1;
        InputStream is;
        byte[] dBuf;
        int dPos, dSize, next;
        StringBuilder builder = new StringBuilder();

        public BlockReader(InputStream is) {
            this(is, 4096);
        }

        public BlockReader(InputStream is, int bufSize) {
            this.is = is;
            dBuf = new byte[bufSize];
            next = nextByte();
        }

        public int nextByte() {
            while (dPos >= dSize) {
                if (dSize == -1) {
                    return EOF;
                }
                dPos = 0;
                try {
                    dSize = is.read(dBuf);
                } catch (Exception e) {
                }
            }
            return dBuf[dPos++];
        }

        public String nextBlock() {
            builder.setLength(0);
            skipBlank();
            while (next != EOF && !Character.isWhitespace(next)) {
                builder.append((char) next);
                next = nextByte();
            }
            return builder.toString();
        }

        public void skipBlank() {
            while (Character.isWhitespace(next)) {
                next = nextByte();
            }
        }

        public int nextInteger() {
            skipBlank();
            int ret = 0;
            boolean rev = false;
            if (next == '+' || next == '-') {
                rev = next == '-';
                next = nextByte();
            }
            while (next >= '0' && next <= '9') {
                ret = (ret << 3) + (ret << 1) + next - '0';
                next = nextByte();
            }
            return rev ? -ret : ret;
        }

        public int nextBlock(char[] data, int offset) {
            skipBlank();
            int index = offset;
            int bound = data.length;
            while (next != EOF && index < bound && !Character.isWhitespace(next)) {
                data[index++] = (char) next;
                next = nextByte();
            }
            return index - offset;
        }

        public boolean hasMore() {
            skipBlank();
            return next != EOF;
        }
    }
}


import java.util.Scanner;

public class Main {
    private static final int P = 1000000007;
    private static long pow(long x, int y) {
        long ret = 1;
        while (y > 0) {
            if (y %2 == 1) {
                ret = ret * x % P;
            }
            x = x * x % P;
            y /= 2;
        }
        return ret;
    }
    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        int n = cin.nextInt();
        int[] a = new int[n + 1];
        long[] rev = new long[n + 1];
        long[] res = new long[2 * n + 1];
        long[][] down = new long[n + 1][n + 1];
        long[][] up = new long[2][2 * n + 1];
        for (int i = 1; i < n; ++i) {
            a[i] = cin.nextInt();
            rev[i] = pow(a[i], P - 2);
        }
        for (int i = n; i > 0; --i) {
            down[i][0] = 1;
            for (int j = 1; j < n; ++j) {
                if (i + j > n) {
                    break;
                }
                down[i][j] = down[i + 1][j - 1] * a[i] % P;
            }
        }

        long number = 1;
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= n; ++j) {
                res[j] = (res[j] + number * down[i][j] % P) % P;
            }
            number = (number * a[i]) % P;
        }
        int pre = 0;
        number = a[1];
        for (int i = 2; i <= n; ++i) {
            int now = 1 - pre;
            for (int j = 0; j <= 2 * n - 2; ++j) {
                up[now][j] = 0;
            }
            up[now][1] = 1;
            for (int j = 2; j <= 2 * n - 2; ++j) {
                if (j - 1 <= n) {
                    up[now][j] = (up[pre][j - 1] + down[i - 1][j - 1] * rev[i - 1] % P * (a[i - 1] - 1) % P) % P;
                } else {
                    up[now][j] = up[pre][j - 1];
                }
            }
            for (int j = 1; j <= 2 * n - 2; ++j) {
                res[j] = (res[j] + number * up[now][j]  % P) % P;
            }
            number = (number * a[i]) % P;
            pre = now;
        }
        for (int i = 1; i <= 2 * n - 2; ++i) {
            System.out.print(res[i] * pow(2, P - 2) % P + " ");
        }
    }
}


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

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

	int MOD = (int)1e9+7;

	public A() {
		FastScanner fs = new FastScanner();
		PrintWriter out = new PrintWriter(System.out);
		System.err.println("");

		int n = fs.nextInt();
		int[] kids = new int[n];
		for(int i = 0; i < n-1; i++) kids[i] = fs.nextInt();

		int[][] walkDown = new int[n][n];
		int[][] walkDown2 = new int[n][n];

		for(int i = 0; i < n; i++) {
			int prod = 1, prod2 = 1;
			for(int j = 1; j < n; j++) {
				if(i + j - 1 >= n) break;

				if(j == 1) prod2 = mult(prod2, Math.max(0, kids[i + j - 1] - 1));
				else prod2 = mult(prod2, kids[i + j - 1]);

				prod = mult(prod, kids[i + j - 1]);

				walkDown[i][j] = prod;
				walkDown2[i][j] = prod2;
			}
		}

		int[][] diagSum = new int[n][n];
		for(int j = 0; j < n; j++) {
			diagSum[0][j] = walkDown2[0][j];
			for(int d = 1; ; d++) {
				int row = 0+d;
				int col = j+d;
				if(row >= n || col >= n) break;
				diagSum[row][col] = walkDown2[row][col];
				diagSum[row][col] = add(diagSum[row][col], diagSum[row-1][col-1]);
			}
		}
		for(int i = 1; i < n; i++) {
			diagSum[i][0] = walkDown[i][0];
			for(int d = 1; ; d++) {
				int row = i+d;
				int col = 0+d;
				if(row >= n || col >= n) break;
				diagSum[row][col] = walkDown2[row][col];
				diagSum[row][col] = add(diagSum[row][col], diagSum[row-1][col-1]);
			}
		}
//		for(int i = 0; i < n; i++) {
//			System.out.println(Arrays.toString(diagSum[i]));
//		}

		int[] freq = new int[n];
		freq[0] = 1;
		for(int i = 1; i < n; i++) {
			freq[i] = mult(freq[i-1], kids[i-1]);
		}

		int[] totWays = new int[2 * n];

		for(int kid = n-1; kid >= 0; kid--) {
			for(int dist = 1; dist <= 2 * n - 2; dist++) {
				int tot = 0;

				if(dist < n) tot = add(tot, walkDown[kid][dist]);

				if(kid > 0) {
					int row = kid-1, col = dist-1;
					if(row >= n || col >= n) {
						int d = Math.max(row-n+1, col-n+1);
						row -= d;
						col -= d;
					}
					int finRow = kid-dist, finCol = 0;
					if(finRow < 0) {
						int add = -finRow;
						finRow += add;
						finCol += add;
					}

					if(row >= finRow) {
						int x = diagSum[row][col];
						if(finRow > 0 && finCol > 0) {
							x -= diagSum[finRow-1][finCol-1];
						}
						tot = add(tot, x);
					}
				}

//				System.out.println(kid + " " + dist + " " + tot);
				if(kid-dist >= 0) tot = add(tot, 1);

				totWays[dist] = add(totWays[dist], mult(tot, freq[kid]));
			}
//			System.out.println();
		}

		int INV2 = (MOD+1)/2;

		for(int i = 0; i < totWays.length; i++) {
			totWays[i] = mult(totWays[i], INV2);
		}

		for(int i = 1; i <= 2 * n - 2; i++) {
			if(i > 1) out.print(" ");
			out.print(totWays[i]);
		}
		out.println();

		out.close();
	}

	int add(int a, int b) {
		a += b;
		if(a >= MOD) a -= MOD;
		return a;
	}

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

	class FastScanner {
		public int BS = 1<<16;
		public char NC = (char)0;
		byte[] buf = new byte[BS];
		int bId = 0, size = 0;
		char c = NC;
		double num = 1;
		BufferedInputStream in;

		public FastScanner() {
			in = new BufferedInputStream(System.in, BS);
		}

		public FastScanner(String s) {
			try {
				in = new BufferedInputStream(new FileInputStream(new File(s)), BS);
			}
			catch (Exception e) {
				in = new BufferedInputStream(System.in, BS);
			}
		}

		public char nextChar(){
			while(bId==size) {
				try {
					size = in.read(buf);
				}catch(Exception e) {
					return NC;
				}
				if(size==-1)return NC;
				bId=0;
			}
			return (char)buf[bId++];
		}

		public int nextInt() {
			return (int)nextLong();
		}

		public long nextLong() {
			num=1;
			boolean neg = false;
			if(c==NC)c=nextChar();
			for(;(c<'0' || c>'9'); c = nextChar()) {
				if(c=='-')neg=true;
			}
			long res = 0;
			for(; c>='0' && c <='9'; c=nextChar()) {
				res = (res<<3)+(res<<1)+c-'0';
				num*=10;
			}
			return neg?-res:res;
		}

		public double nextDouble() {
			double cur = nextLong();
			return c!='.' ? cur:cur+nextLong()/num;
		}

		public String next() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c>32) {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public String nextLine() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c!='\n') {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public boolean hasNext() {
			if(c>32)return true;
			while(true) {
				c=nextChar();
				if(c==NC)return false;
				else if(c>32)return true;
			}
		}

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

	}

}


import java.io.*;
import java.util.*;
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskE solver = new TaskE();
        solver.solve(1, in, out);
        out.flush();out.close();
    }
        static class TaskE {
          long mod=(long)(1E9)+7;
          long rpe(long a){long b=mod-2;
           long ans=1;
           while(b!=0){
            if(b%2!=0)ans=(ans*a)%mod;
            b/=2;a=a*a%mod;
           }return ans;
          }
          long i2=rpe(2);
          long f(long c){
           return c*(c-1+mod)%mod*i2%mod;
          }
          public void solve(int testNumber, InputReader in, PrintWriter out) {
           int n=in.nextInt();
           long a[]=new long[n+10];for(int i=1;i<=n-1;i++)a[i]=in.nextLong();a[0]=1;
           long c=1;long ans[]=new long[2*n-1];
           for(int i=2;i<=n;i++){
            c=(c*a[i-1])%mod;
            for(int j=i-1;j>=1;j--){
             long m=1;
             for(int k=i-j;k<=2*(i-j);k++){
              long v=c*m%mod;if(k==2*(i-j))v=v*i2%mod;//f(a[j])*a[j-1]%mod;
              ans[k]=(ans[k]+v)%mod;
              if(k==i-j)m=m*(a[j+k-(i-j)]-1+mod)%mod;
              else m=m*a[j+k-(i-j)]%mod;
             }
            }
           }
           for(int i=1;i<2*n-1;i++)out.print(ans[i]+" ");
          }
         /*pair ja[][];long w[];int from[],to[],c[];
             void make(int n,int m,InputReader in){
              ja=new pair[n+1][];w=new long[m];from=new int[m];to=new int[m];c=new int[n+1];
              for(int i=0;i<m;i++){
               int u=in.nextInt(),v=in.nextInt();long wt=in.nextLong();
               c[u]++;c[v]++;from[i]=u;to[i]=v;w[i]=wt;
              }
              for(int i=1;i<=n;i++){
               ja[i]=new pair[c[i]];c[i]=0;
              }
              for(int i=0;i<m;i++){
               ja[from[i]][c[from[i]]++]=new pair(to[i],w[i]);
               ja[to[i]][c[to[i]]++]=new pair(from[i],w[i]);
              }
             }*/
        int[] radixSort(int[] f){ return radixSort(f, f.length); }
	int[] radixSort(int[] f, int n)
	{
		int[] to = new int[n];
		{
			int[] b = new int[65537];
			for(int i = 0;i < n;i++)b[1+(f[i]&0xffff)]++;
			for(int i = 1;i <= 65536;i++)b[i]+=b[i-1];
			for(int i = 0;i < n;i++)to[b[f[i]&0xffff]++] = f[i];
			int[] d = f; f = to;to = d;
		}
		{
			int[] b = new int[65537];
			for(int i = 0;i < n;i++)b[1+(f[i]>>>16)]++;
			for(int i = 1;i <= 65536;i++)b[i]+=b[i-1];
			for(int i = 0;i < n;i++)to[b[f[i]>>>16]++] = f[i];
			int[] d = f; f = to;to = d;
		}
		return f;
	}
    }
    static class InputReader {
        BufferedReader br;
        StringTokenizer st;
        public InputReader(InputStream stream) {
            br = new BufferedReader(new InputStreamReader(stream));
            st = null;
        }

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

        boolean hasMoreTokens() {
            while (st == null || !st.hasMoreTokens()) {
                String s = null;
                try {
                    s = br.readLine();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (s == null)
                    return false;
                st = new StringTokenizer(s);
            }
            return true;
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }
        public long nextLong() {
            return Long.parseLong(next());
        }
        public double nextDouble() {
            return Double.parseDouble(next());
        }
    }
}


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

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

	static final int MD = 1000000007;
	long power(int a, int k) {
		if (k == 0)
			return 1;
		long p = power(a, k >> 1);
		p = p * p % MD;
		if ((k & 1) == 1)
			p = p * a % MD;
		return p;
	}
	void main() {
		int n = sc.nextInt();
		int x = sc.nextInt();
		byte[] cc = sc.next().getBytes();
		if (x == 0) {
			println(n == 1 && cc[0] == '0' ? 1 : 0);
			return;
		}
		int[] ff = new int[x + 1];
		ff[0] = ff[1] = 1;
		for (int i = 2; i <= x; i++)
			ff[i] = (ff[i - 1] + ff[i - 2]) % (MD - 1);
		for (int i = 0; i <= x; i++)
			ff[i] = (int) power(2, ff[i]);
		int[][][] ds = new int[x + 1][n][n + 1];
		for (int l = 0; l < n; l++) {
			ds[0][l][l] = ds[1][l][l] = 1;
			ds[0][l][l + 1] = cc[l] == '0' ? 1 : 0;
			ds[1][l][l + 1] = cc[l] == '1' ? 1 : 0;
		}
		for (int i = 2; i <= x; i++)
			for (int l = 0; l < n; l++)
				for (int r = l; r < n; r++) {
					long z = 0;
					for (int m = l; m <= r; m++)
						z = (z + (long) ds[i - 1][l][m] * ds[i - 2][m][r]) % MD;
					ds[i][l][r] = (int) z;
				}
		int[][] dp = new int[x + 1][n];
		int[][] dq = new int[x + 1][n];
		if (n > 1) {
			dp[0][n - 1] = ds[0][n - 1][n];
			dp[1][n - 1] = ds[1][n - 1][n];
			for (int i = 2; i <= x; i++)
				for (int l = 1; l < n; l++) {
					long z = (long) dp[i - 1][l] * ff[i - 2] % MD;
					for (int m = l; m < n; m++)
						z = (z + (long) ds[i - 1][l][m] * dp[i - 2][m]) % MD;
					dp[i][l] = (int) z;
				}
			dq[0][1] = ds[0][0][1];
			dq[1][1] = ds[1][0][1];
			for (int i = 2; i <= x; i++)
				for (int r = 1; r < n; r++) {
					long z = (long) ff[i - 1] * dq[i - 2][r] % MD;
					for (int m = r; m > 0; m--)
						z = (z + (long) dq[i - 1][m] * ds[i - 2][m][r]) % MD;
					dq[i][r] = (int) z;
				}
		}
		int[] dr = new int[x + 1];
		dr[0] = ds[0][0][n];
		dr[1] = ds[1][0][n];
		for (int i = 2; i <= x; i++) {
			long z = ((long) dr[i - 1] * ff[i - 2] + (long) ff[i - 1] * dr[i - 2]) % MD;
			for (int m = 1; m < n; m++)
				z = (z + (long) dq[i - 1][m] * dp[i - 2][m]) % MD;
			dr[i] = (int) z;
		}
		println(dr[x]);
	}
}


import java.io.*;

/**
 * Created by dalt on 2018/3/25.
 */
public class CF946F {
    public static BlockReader input;
    public static PrintStream output;
    public static void main(String[] args) throws FileNotFoundException {
        if (System.getProperty("ONLINE_JUDGE") == null) {
            input = new BlockReader(new FileInputStream("D:\\DataBase\\TESTCASE\\codeforces\\CF946F.in"));
            output = System.out;
        }else{
            input = new BlockReader(System.in);
            output = new PrintStream(new BufferedOutputStream(System.out), false);
        }

        solve();

        output.flush();
    }

    public static void solve() {
        int n = input.nextInteger();
        int x = input.nextInteger();
        String s = input.nextBlock();
        int slen = s.length();
        final long MOD = 1000000007;
        final int ALIGN_LEFT = 0;
        final int ALIGN_RIGHT = 1;
        final int ALIGN_CENTER = 2;
        final int ALIGN_LEFT_RIGHT = 3;

        long[][][][] dp = new long[Math.max(x + 1, 2)][slen + 1][slen + 1][4];
        long[] lengthes = new long[101];
        lengthes[0] = lengthes[1] = 1;

        for (int j = 0, bound = 2; j < bound; j++) {
            for (int i = 0; i <= slen; i++) {
                for (int k = 0; k < 4; k++) {
                    dp[j][i][i][ALIGN_LEFT] = 2;
                    dp[j][i][i][ALIGN_RIGHT] = 2;
                    dp[j][i][i][ALIGN_CENTER] = 2;
                    dp[j][i][i][ALIGN_LEFT_RIGHT] = 1;
                }
            }
        }

        for (int i = 0; i < slen; i++) {
            int c = s.charAt(i) - '0';
            dp[c][i][i + 1][ALIGN_LEFT] = 1;
            dp[c][i][i + 1][ALIGN_RIGHT] = 1;
            dp[c][i][i + 1][ALIGN_CENTER] = 1;
            dp[c][i][i + 1][ALIGN_LEFT_RIGHT] = 1;
        }

        for (int i = 2; i <= x; i++) {
            int last = i - 1;
            int last2 = i - 2;
            lengthes[i] = (lengthes[last] + lengthes[last2]) % (MOD - 1);

            long pLast = pow(2, lengthes[last], MOD);
            long pLast2 = pow(2, lengthes[last2], MOD);
            for (int j = 0; j <= slen; j++) {
                dp[i][j][j][ALIGN_LEFT] = pLast * pLast2 % MOD;
                dp[i][j][j][ALIGN_RIGHT] = dp[i][j][j][ALIGN_LEFT];
                dp[i][j][j][ALIGN_CENTER] = dp[i][j][j][ALIGN_LEFT];
                dp[i][j][j][ALIGN_LEFT_RIGHT] = 1;
                for (int k = j + 1; k <= slen; k++) {
                    dp[i][j][k][ALIGN_LEFT] = (dp[last][j][k][ALIGN_LEFT] * pLast2 + dp[last2][j][k][ALIGN_LEFT]) % MOD;
                    dp[i][j][k][ALIGN_RIGHT] = (dp[last][j][k][ALIGN_RIGHT] + pLast * dp[last2][j][k][ALIGN_RIGHT]) % MOD;
                    dp[i][j][k][ALIGN_CENTER] = (dp[last][j][k][ALIGN_CENTER] * pLast2 + pLast * dp[last2][j][k][ALIGN_CENTER]) % MOD;
                    dp[i][j][k][ALIGN_LEFT_RIGHT] = (dp[last][j][k][ALIGN_LEFT_RIGHT] + dp[last2][j][k][ALIGN_LEFT_RIGHT]) % MOD;
                    for (int sep = j + 1; sep < k; sep++) {
                        dp[i][j][k][ALIGN_LEFT] = (dp[i][j][k][ALIGN_LEFT] + dp[last][j][sep][ALIGN_LEFT_RIGHT] * dp[last2][sep][k][ALIGN_LEFT]) % MOD;
                        dp[i][j][k][ALIGN_RIGHT] = (dp[i][j][k][ALIGN_RIGHT] + dp[last][j][sep][ALIGN_RIGHT] * dp[last2][sep][k][ALIGN_LEFT_RIGHT]) % MOD;
                        dp[i][j][k][ALIGN_LEFT_RIGHT] = (dp[i][j][k][ALIGN_LEFT_RIGHT] + dp[last][j][sep][ALIGN_LEFT_RIGHT] * dp[last2][sep][k][ALIGN_LEFT_RIGHT]) % MOD;
                        dp[i][j][k][ALIGN_CENTER] = (dp[i][j][k][ALIGN_CENTER] + dp[last][j][sep][ALIGN_RIGHT] * dp[last2][sep][k][ALIGN_LEFT]) % MOD;
                    }
                }
            }
        }

         System.out.println(dp[x][0][slen][ALIGN_CENTER]);
    }

    public static long pow(long x, long n, long MOD) {
        int bit = 31;
        for (; bit >= 0 && (n & (1 << bit)) == 0; bit--) ;
        long product = 1;
        for (; bit >= 0; bit--) {
            product = (product * product) % MOD;
            if ((n & (1 << bit)) != 0) {
                product = (product * x) % MOD;
            }
        }
        return (int) product;
    }

    public static class BlockReader {
        static final int EOF = -1;
        InputStream is;
        byte[] dBuf;
        int dPos, dSize, next;
        StringBuilder builder = new StringBuilder();

        public BlockReader(InputStream is) {
            this(is, 4096);
        }

        public BlockReader(InputStream is, int bufSize) {
            this.is = is;
            dBuf = new byte[bufSize];
            next = nextByte();
        }

        public int nextByte() {
            while (dPos >= dSize) {
                if (dSize == -1) {
                    return EOF;
                }
                dPos = 0;
                try {
                    dSize = is.read(dBuf);
                } catch (Exception e) {
                }
            }
            return dBuf[dPos++];
        }

        public String nextBlock() {
            builder.setLength(0);
            skipBlank();
            while (next != EOF && !Character.isWhitespace(next)) {
                builder.append((char) next);
                next = nextByte();
            }
            return builder.toString();
        }

        public void skipBlank() {
            while (Character.isWhitespace(next)) {
                next = nextByte();
            }
        }

        public int nextInteger() {
            skipBlank();
            int ret = 0;
            boolean rev = false;
            if (next == '+' || next == '-') {
                rev = next == '-';
                next = nextByte();
            }
            while (next >= '0' && next <= '9') {
                ret = (ret << 3) + (ret << 1) + next - '0';
                next = nextByte();
            }
            return rev ? -ret : ret;
        }

        public int nextBlock(char[] data, int offset) {
            skipBlank();
            int index = offset;
            int bound = data.length;
            while (next != EOF && index < bound && !Character.isWhitespace(next)) {
                data[index++] = (char) next;
                next = nextByte();
            }
            return index - offset;
        }

        public boolean hasMore() {
            skipBlank();
            return next != EOF;
        }
    }
}


import java.util.*;
import java.io.*;
import java.lang.*;
import java.math.*;
public class F {
    public static void main(String[] args) throws Exception {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        // Scanner scan = new Scanner(System.in);
        // PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
        // int n = Integer.parseInt(bf.readLine());
        StringTokenizer st = new StringTokenizer(bf.readLine());
        // int[] a = new int[n];
        // for(int i=0; i<n; i++) a[i] =  Integer.parseInt(st.nextToken());
        int n = Integer.parseInt(st.nextToken());
        int x = Integer.parseInt(st.nextToken());
        String s = bf.readLine();
        int mod = 1000000007;
        int[][][] dp = new int[n][n][x+1];
        int[][][] dp_begin = new int[n][n][x+1];
        int[][][] dp_end = new int[n][n][x+1];
        int[][][] dp_final = new int[n][n][x+1];
        int[] fibonacci = new int[x+1];
        fibonacci[0] = 1;
        if(x >= 1) fibonacci[1] = 1;
        for(int i=2; i<=x; i++)
          fibonacci[i] = (int)((fibonacci[i-1] + fibonacci[i-2]) % (mod - 1));
        for(int i=0; i<n; i++) {

              if(s.charAt(i) == '1') dp[i][i][1] = 1;
              if(s.charAt(i) == '0') dp[i][i][0] = 1;
              if(s.charAt(i) == '1') dp_begin[i][i][1] = 1;
              if(s.charAt(i) == '0') dp_begin[i][i][0] = 1;
              if(s.charAt(i) == '1') dp_end[i][i][1] = 1;
              if(s.charAt(i) == '0') dp_end[i][i][0] = 1;
              if(s.charAt(i) == '1') dp_final[i][i][1] = 1;
              if(s.charAt(i) == '0') dp_final[i][i][0] = 1;

        }
        int[] exponential = new int[x+1];
        for(int i=0; i<=x; i++) exponential[i] = exp(2, fibonacci[i], mod);
        for(int k=2; k<=x; k++) {
          for(int i=0; i<n; i++) {
            for(int j=i; j<n; j++) {

              int sum = 0;
              long toAdd = 1;
              for(int c=0; c<=j-i+1; c++) {
                toAdd = 1;
                if(c != 0) toAdd *= dp[i][i+c-1][k-1];
                if(c != j-i+1) toAdd *= dp[i+c][j][k-2];
                toAdd %= mod;

                sum = (int)((0L + sum + toAdd) % mod);
              }
              dp[i][j][k] = sum;
            }
          }
        }
        for(int k=2; k<=x; k++) {
          for(int i=0; i<n; i++) {
            for(int j=i; j<n; j++) {

              int sum = 0;
              long toAdd = 1;
              for(int c=0; c<=j-i+1; c++) {
                toAdd = 1;
                if((c != 0) && (c != j-i+1)) {
                  toAdd *= dp_begin[i][i+c-1][k-1];
                  toAdd *= dp[i+c][j][k-2];
                }
                else if(c == 0) {
                  toAdd *= exponential[k-1];
                  toAdd *= dp_begin[i+c][j][k-2];
                }
                else if(c == j-i+1)  {
                  toAdd *= dp_begin[i][i+c-1][k-1];
                }
                toAdd %= mod;
                sum = (int)((0L + sum + toAdd) % mod);
              }
              dp_begin[i][j][k] = sum;
            }
          }
        }
        for(int k=2; k<=x; k++) {
          for(int i=0; i<n; i++) {
            for(int j=i; j<n; j++) {

              int sum = 0;
              long toAdd = 1;
              for(int c=0; c<=j-i+1; c++) {
                toAdd = 1;
                if((c != 0) && (c != j-i+1)) {
                  toAdd *= dp[i][i+c-1][k-1];
                  toAdd *= dp_end[i+c][j][k-2];
                }
                else if(c == 0) {

                  toAdd *= dp_end[i+c][j][k-2];
                }
                else if(c == j-i+1)  {
                  toAdd *= exponential[k-2];
                  toAdd *= dp_end[i][i+c-1][k-1];
                }
                toAdd %= mod;
                sum = (int)((0L + sum + toAdd) % mod);
              }
              dp_end[i][j][k] = sum;
            }
          }
        }
        for(int k=2; k<=x; k++) {
          for(int i=0; i<n; i++) {
            for(int j=i; j<n; j++) {

              int sum = 0;
              long toAdd = 1;
              for(int c=0; c<=j-i+1; c++) {
                toAdd = 1;
                if((c != 0) && (c != j-i+1)) {
                  toAdd *= dp_begin[i][i+c-1][k-1];
                  toAdd *= dp_end[i+c][j][k-2];
                }
                else if(c == 0) {
                  toAdd *= 1L*exponential[k-1]*dp_final[i+c][j][k-2];

                }
                else if(c == j-i+1) {
                  toAdd *= 1L*dp_final[i][i+c-1][k-1]*exponential[k-2];
                }

                toAdd %= mod;
                sum = (int)((0L + sum + toAdd) % mod);
              }
              dp_final[i][j][k] = sum;
            }
          }
        }
        //System.out.println(dp[0][0][3]);
      //  System.out.println("Occurences: " + dp[0][n-1][x]);
        int ans = dp_final[0][n-1][x];

        System.out.println(ans);
        // out.close(); System.exit(0);
    }

    public static int exp(int base, int e, int mod) {
      if(e == 0) return 1;
      if(e == 1) return base;
      int val = exp(base, e/2, mod);
      int ans = (int)(1L*val*val % mod);
      if(e % 2 == 1)
        ans = (int)(1L*ans*base % mod);
      return ans;
    }
}


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

public class F946{

    long[] fibpow;
    char[] chs;
    long mod = 1000000007L;
    long modpow = mod-1L;
    long[][][] memo;

    long pow(long m, long n){
        long res = 1;
        while(n > 0){
            if(n % 2 == 1)res = (res*m)%mod;
            m = (m*m)%mod;
            n = n/2;
        }
        return res;
    }

    private void solve() throws Exception {
        int n = nextInt();
        int x = nextInt();
        chs = nextToken().toCharArray();
        memo = new long[n][n][x+1];
        for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) Arrays.fill(memo[i][j], -1);
        fibpow = new long[x+1];
        fibpow[1] = 1L;
        for(int i = 2; i <= x; i++) fibpow[i] = (fibpow[i-1]+ fibpow[i-2])%modpow;
        for(int i = 0; i <= x; i++) fibpow[i] = pow(2, fibpow[i]);
        out.println(doit(0,n-1,x));
    }

    long doit(int i, int j, int x) {
        if (x < 2 && i == j && chs[i]-'0' == x) return 1L;
        else if (x < 2 && i == j && chs[i]-'0' != x) return 0L;
        else if(x < 2 && i < j) return 0L;
        else if(memo[i][j][x] < 0){
            long res = 0L;
            res = (res + ((i==0?fibpow[x]:(1L)) * doit(i,j, x-2))%mod)%mod;
            for(int t = i; t < j; t++) res = (res + (doit(i,t,x-1) * doit(t+1,j, x-2))%mod)%mod;
            res = (res + (doit(i,j,x-1) * (j==chs.length-1? fibpow[x-1]:(1L)))%mod)%mod;
            memo[i][j][x] = res;
        }
        return memo[i][j][x];
    }

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

    private BufferedReader in;
    private PrintWriter out;
    private StringTokenizer tokenizer;

    public void run() {
        try {
            in = new BufferedReader(new InputStreamReader(System.in));
            tokenizer = null;
            out = new PrintWriter(System.out);
            solve();
            in.close();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
    }

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

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

    private float nextFloat() throws IOException {
        return Float.parseFloat(nextToken());
    }

    private String nextLine() throws IOException {
        return new String(in.readLine());
    }

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

}


import java.util.*;
import java.io.*;
import java.math.*;
import java.lang.*;
import java.awt.*;
import java.awt.geom.*;
import java.util.stream.*;

/**
 * @author Pradyumn
 */

public class Main implements Runnable{
	public int TC = 0;
	public static void main(String[] args) {
		new Thread(null, new Main(), ":)", 1L << 26).start();
	}
	static final int MODULO = (int)(1e9 + 7);
	@SuppressWarnings("Unchecked")
	public void solve() throws IOException {
	    int n = ni();
	    HashSet<Integer> x = new HashSet<>();
	    HashSet<Integer> y = new HashSet<>();
	    HashMap<Integer, Integer> mapX = new HashMap<>();
	    HashMap<Integer, Integer> mapY = new HashMap<>();
	    int[][] pp = new int[2][n];
	    for (int i = 0; i < n;  ++i) {
	    	for(int j = 0;j < 2; ++j) {
	    		pp[j][i] = ni();
	    		if(j == 0) x.add(pp[j][i]);
	    		else y.add(pp[j][i]);
	    	}
	    }

	    int mapIdx = 0;
	    for(int xx : x)
	    	if(!mapX.containsKey(xx))
	    		mapX.put(xx, mapIdx++);

	    for(int yy : y)
	    	if(!mapY.containsKey(yy))
	    		mapY.put(yy, mapIdx++);

	    UnionFind uf = new UnionFind(mapIdx);
	    for(int i = 0;i < n; ++i) {
	    	uf.unionSet(mapX.get(pp[0][i]), mapY.get(pp[1][i]));
	    }
	    uf.close();

	    long res = 1;
	    factorial();
	    for (int i = 0; i < mapIdx; i++)
            if (uf.p[i] == i) {
                int numPoints = uf.numPoints[i], lines = uf.sizeOfSet(i);
                long ways = 0;
                for (int j = 0; j <= Math.min(numPoints, lines); j++) {
                    ways += ncr(lines, j);
                    if (ways >= MODULO) ways -= MODULO;
                }
                res *= ways;
                res %= MODULO;

            }
	    out.println(res);
	}
	// O(1) nCr
    static int MAX = 5 * 100000 + 1;
    static int fact[] = new int[MAX];

    static int ncr(int n, int r) {
        return (int) ((long) fact[n] * ((inv(fact[r], MODULO) * inv(fact[n - r], MODULO)) % MODULO) % MODULO) % MODULO;
    }

    static long inv(long x, long mod) {
        long r, y;
        for (r = 1, y = mod - 2; y != 0; x = x * x % mod, y >>= 1)
            if ((y & 1) == 1)
                r = r * x % mod;
        return r;
    }

    static void factorial() {
        fact[0] = fact[1] = 1;
        for (int i = 2; i < MAX; i++)
            fact[i] = (int) ((long) i * fact[i - 1] % MODULO);
    }

    public static long modular_exponentiation(long a, long b, long c) // returns ( a ^ b ) % c
    {
        long ans = 1L;
        while (b != 0) {
            if ((b & (1)) == 1)
                ans = (ans * a) % c;

            a = (a * a) % c;
            b >>= 1L;
        }

        return ans;
    }
	static class UnionFind {
        private int[] p, rank, setSize, numPoints;
        private int numSets;

        public UnionFind(int size) {
            p = new int[size];
            rank = new int[size];
            setSize = new int[size];
            numPoints = new int[size];
            numSets = size;
            for (int i = 0; i < size; ++i) {
                p[i] = i;
                numPoints[i] = 0;
                setSize[i] = 1;
            }
        }

        int findSet(int i) {
            return (p[i] == i) ? i : (p[i] = findSet(p[i]));
        }

        boolean isSameSet(int i, int j) {
            return findSet(i) == findSet(j);
        }

        void unionSet(int i, int j) {
            if (!isSameSet(i, j)) {
                --numSets;
                int x = findSet(i), y = findSet(j);
                if (rank[x] > rank[y]) {
                    p[y] = x;
                    setSize[x] = setSize[x] + setSize[y];
                    numPoints[x] = 1 + numPoints[x] + numPoints[y];
                } else {
                    p[x] = y;
                    setSize[y] = setSize[y] + setSize[x];
                    numPoints[y] = numPoints[y] + numPoints[x] + 1;
                    if (rank[x] == rank[y]) ++rank[y];
                }
            } else {
                numPoints[findSet(i)]++;
            }
        }

        int numDisjointSets() {
            return numSets;
        }

        void close() {
            for (int i = 0; i < p.length; i++)
                findSet(i);
        }

        int sizeOfSet(int i) {
            return setSize[findSet(i)];
        }
    }
	BufferedReader br;
	StringTokenizer st;
	PrintWriter out;
	public void run() {
		try {
			br = new BufferedReader(new InputStreamReader(System.in),32768);
			st = null;
			out = new PrintWriter(System.out);
			if(TC == 1) {
				for(int T = ni();T > 0; --T) {
					solve();
				}
			} else {
				solve();
			}
			br.close();
			out.close();
		} catch(IOException e) {
			e.printStackTrace();
			System.exit(1);
		}
	}
	public char[] nsc( ) throws IOException {
		return ns().toCharArray();
	}
	public char[][] nm(int n, int m) throws IOException {
		char[][] map = new char[n][];
		for(int i = 0;i < n; ++i) {
			map[i] = nsc();
		}
		return map;
	}
	public String ns() throws IOException {
		while (st == null || !st.hasMoreTokens()) {
			st = new StringTokenizer(br.readLine());
		}
		return st.nextToken();
	}
	public String nextLine() throws IOException {
		return br.readLine();
	}
	public int ni() throws IOException {
		return Integer.parseInt(ns());
	}

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

	public long nl() throws IOException {
		return Long.parseLong(ns());
	}

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

	public double nd() throws IOException {
		return Double.parseDouble(ns());
	}
	private static boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	private static void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}


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

public class Main {

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

        Scanner sc = new Scanner(System.in);
        PrintWriter out = new PrintWriter(System.out);

        int n = sc.nextInt();
        HashSet<Integer> x = new HashSet<>(), y = new HashSet<>();
        HashMap<Integer, Integer> mapX = new HashMap<>(), mapY = new HashMap<>();
        int[][] arr = new int[2][n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < 2; j++) {
                arr[j][i] = sc.nextInt();
                if (j == 0) x.add(arr[j][i]);
                else y.add(arr[j][i]);
            }
        }

        int mapIdxX = 0;
        for (int xx : x) if (!mapX.containsKey(xx)) mapX.put(xx, mapIdxX++);
        for (int yy : y) if (!mapY.containsKey(yy)) mapY.put(yy, mapIdxX++);

        UnionFind uf = new UnionFind(mapIdxX);
        for (int i = 0; i < n; i++)
            uf.unionSet(mapX.get(arr[0][i]), mapY.get(arr[1][i]));

        uf.close();
        long res = 1;
        int mod = (int) 1e9 + 7;
        factorial();
        for (int i = 0; i < mapIdxX; i++)
            if (uf.p[i] == i) {
                int numPoints = uf.numPoints[i], lines = uf.sizeOfSet(i);
                long ways = 0;
                for (int j = 0; j <= Math.min(numPoints, lines); j++) {
                    ways += ncr(lines, j);
                    if (ways >= mod) ways -= mod;
                }
                res *= ways;
                res %= mod;

            }

        out.println(res);
        out.close();
    }

    // O(1) nCr
    static int MAX = 5 * 100000 + 1;
    static int fact[] = new int[MAX];
    static int MOD = (int) 1e9 + 7;

    static int ncr(int n, int r) {
        return (int) ((long) fact[n] * ((inv(fact[r], MOD) * inv(fact[n - r], MOD)) % MOD) % MOD) % MOD;
    }

    static long inv(long x, long mod) {
        long r, y;
        for (r = 1, y = mod - 2; y != 0; x = x * x % mod, y >>= 1)
            if ((y & 1) == 1)
                r = r * x % mod;
        return r;
    }

    static void factorial() {
        fact[0] = fact[1] = 1;
        for (int i = 2; i < MAX; i++)
            fact[i] = (int) ((long) i * fact[i - 1] % MOD);
    }

    public static long modular_exponentiation(long a, long b, long c) // returns ( a ^ b ) % c
    {
        long ans = 1L;
        while (b != 0) {
            if ((b & (1)) == 1)
                ans = (ans * a) % c;

            a = (a * a) % c;
            b >>= 1L;
        }

        return ans;
    }

    static class UnionFind {
        private int[] p, rank, setSize, numPoints;
        private int numSets;

        public UnionFind(int size) {
            p = new int[size];
            rank = new int[size];
            setSize = new int[size];
            numPoints = new int[size];
            numSets = size;
            for (int i = 0; i < size; ++i) {
                p[i] = i;
                numPoints[i] = 0;
                setSize[i] = 1;
            }
        }

        int findSet(int i) {
            return (p[i] == i) ? i : (p[i] = findSet(p[i]));
        }

        boolean isSameSet(int i, int j) {
            return findSet(i) == findSet(j);
        }

        void unionSet(int i, int j) {
            if (!isSameSet(i, j)) {
                --numSets;
                int x = findSet(i), y = findSet(j);
                if (rank[x] > rank[y]) {
                    p[y] = x;
                    setSize[x] = setSize[x] + setSize[y];
                    numPoints[x] = 1 + numPoints[x] + numPoints[y];
                } else {
                    p[x] = y;
                    setSize[y] = setSize[y] + setSize[x];
                    numPoints[y] = numPoints[y] + numPoints[x] + 1;
                    if (rank[x] == rank[y]) ++rank[y];
                }
            } else {
                numPoints[findSet(i)]++;
            }
        }

        int numDisjointSets() {
            return numSets;
        }

        void close() {
            for (int i = 0; i < p.length; i++)
                findSet(i);
        }

        int sizeOfSet(int i) {
            return setSize[findSet(i)];
        }
    }

    static class Scanner {
        StringTokenizer st;
        BufferedReader br;

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

        public Scanner(String s) throws FileNotFoundException {
            br = new BufferedReader(new FileReader(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 {
            return Double.parseDouble(next());
        }

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


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ByteArrayOutputStream;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.StringTokenizer;
import java.util.Map;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Set;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.FileNotFoundException;
import java.io.File;
import java.util.List;
import java.util.TreeMap;
import java.io.Writer;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.InputStream;

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

  static class E extends SimpleSavingChelperSolution {
    private int[] x;
    private int[] y;
    private int n;
    private Map<Integer, Integer> xMap;
    private Map<Integer, Integer> yMap;
    private List<Set<Integer>> edges;
    private boolean[] visited;
    private long MOD;

    public void solve(int testNumber, InputReader in, OutputWriter out) {
      wrapSolve(testNumber, in, out);
    }

    public void solve(int testNumber) {
      n = in.nextInt();

      x = new int[n];
      y = new int[n];

      xMap = new TreeMap<>();
      yMap = new TreeMap<>();

      edges = new ArrayList<>();

      for (int i = 0; i < n; i++) {
        edges.add(new HashSet<>());
      }

      Map<Integer, Integer> prevX = new HashMap<>();
      Map<Integer, Integer> prevY = new HashMap<>();

      for (int i = 0; i < n; i++) {
        x[i] = in.nextInt();
        y[i] = in.nextInt();

        xMap.put(x[i], xMap.getOrDefault(x[i], 0) + 1);
        yMap.put(y[i], yMap.getOrDefault(y[i], 0) + 1);

        Integer pX = prevX.get(x[i]);
        Integer pY = prevY.get(y[i]);

        if (pX != null) {
          edges.get(pX).add(i);
          edges.get(i).add(pX);
        }
        if (pY != null) {
          edges.get(pY).add(i);
          edges.get(i).add(pY);
        }

        prevX.put(x[i], i);
        prevY.put(y[i], i);
      }

      visited = new boolean[n];

      long ans = 1;

      MOD = 1000000007;

      for (int i = 0; i < n; i++) {
        if (visited[i]) {
          continue;
        }

        List<Integer> res = new ArrayList<>();
        dfs(i, res);

        Set<Integer> usedX = new HashSet<>();
        Set<Integer> usedY = new HashSet<>();

        for (Integer j : res) {
          usedX.add(x[j]);
          usedY.add(y[j]);
        }

        int K = usedX.size() + usedY.size();
        if (res.size() >= K) {
          ans = ans * twopow(K) % MOD;
        } else {
          ans = ans * ((twopow(K) - 1 + MOD) % MOD) % MOD;
        }
      }

      out.println(ans);
    }

    long twopow(int n) {
      if (n == 0) {
        return 1;
      }
      if (n % 2 == 0) {
        long t = twopow(n / 2);
        return t * t % MOD;
      }
      return twopow(n - 1) * 2 % MOD;
    }

    void dfs(int v, List<Integer> res) {
      if (visited[v]) {
        return;
      }
      visited[v] = true;
      res.add(v);

      for (int j : edges.get(v)) {
        dfs(j, res);
      }
    }

  }

  static class InputReader {
    private BufferedReader br;
    private StringTokenizer in;

    public InputReader(String fileName) {
      try {
        br = new BufferedReader(new FileReader(fileName));
      } catch (IOException e) {
        throw new RuntimeException(e);
      }
    }

    public InputReader(InputStream inputStream) {
      br = new BufferedReader(new InputStreamReader(inputStream));
    }

    private boolean hasMoreTokens() {
      while (in == null || !in.hasMoreTokens()) {
        String s = nextLine();
        if (s == null) {
          return false;
        }
        in = new StringTokenizer(s);
      }
      return true;
    }

    public String nextString() {
      return hasMoreTokens() ? in.nextToken() : null;
    }

    public String nextLine() {
      try {
        in = null;
        return br.readLine();
      } catch (Exception e) {
        e.printStackTrace();
        return null;
      }
    }

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

  }

  static class OutputWriter extends PrintWriter {

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

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

    public OutputWriter(OutputStream outputStream) {
      super(outputStream);
    }

    public OutputWriter(Writer writer) {
      super(writer);
    }

  }

  static abstract class SimpleSavingChelperSolution extends SavingChelperSolution {

    public String processOutputPreCheck(int testNumber, String output) {
      return output;
    }

    public String processOutputPostCheck(int testNumber, String output) {
      return output;
    }

  }

  static abstract class SavingChelperSolution {
    protected int testNumber;
    public InputReader in;
    public OutputWriter out;
    private OutputWriter toFile;
    private boolean local = new File("chelper.properties").exists();
    public OutputWriter debug;

    {
      if (local) {
        debug = new OutputWriter(System.out);
      } else {
        debug = new OutputWriter(new OutputStream() {

          public void write(int b) {
          }
        });
      }
    }

    public SavingChelperSolution() {
      try {
        toFile = new OutputWriter("last_test_output.txt");
      } catch (FileNotFoundException e) {
        throw new RuntimeException(e);
      }
    }

    public abstract void solve(int testNumber);

    public abstract String processOutputPreCheck(int testNumber, String output);

    public abstract String processOutputPostCheck(int testNumber, String output);

    public void wrapSolve(int testNumber, InputReader in, OutputWriter out) {
      this.testNumber = testNumber;

      ByteArrayOutputStream substituteOutContents = new ByteArrayOutputStream();
      OutputWriter substituteOut = new OutputWriter(substituteOutContents);

      this.in = in;
      this.out = substituteOut;

      solve(testNumber);
      substituteOut.flush();

      String result = substituteOutContents.toString();

      result = processOutputPreCheck(testNumber, result);
      out.print(result);
      out.flush();

      if (local) {
        debug.flush();

        result = processOutputPostCheck(testNumber, result);
        toFile.print(result);
        toFile.flush();
      }
    }

  }
}


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

import static java.lang.Math.random;

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

    int N = (int) 1e5 + 10;
    int MOD = (int) 1e9 + 7;

    int n;
    int[][] p;
    List<Integer>[] G;

    boolean[] used = new boolean[N];
    Set<Integer> uniqueX = new HashSet<>(), uniqueY = new HashSet<>();
    long sumDegree = 0, numNode = 0;

    void solve() {
        n = in.nextInt();

        p = new int[n][2];
        for (int i = 0; i < n; i++) {
            p[i][0] = in.nextInt();
            p[i][1] = in.nextInt();
        }

        int[] x = new int[n], y = new int[n];
        for (int i = 0; i < n; i++) {
            x[i] = p[i][0];
            y[i] = p[i][1];
        }
        sort(x);
        sort(y);
        for (int i = 0; i < n; i++) {
            p[i][0] = lowerBound(x, p[i][0]);
            p[i][1] = lowerBound(y, p[i][1]);
        }

        G = new List[n];
        for (int i = 0; i < n; i++) G[i] = new ArrayList<>();

        List<Integer>[] ver = new List[n], hor = new List[n];
        for (int i = 0; i < n; i++) {
            ver[i] = new ArrayList<>();
            hor[i] = new ArrayList<>();
        }
        for (int i = 0; i < n; i++) {
            ver[p[i][0]].add(i);
            hor[p[i][1]].add(i);
        }
        for (int i = 0; i < n; i++) {
            ver[i].sort(Comparator.comparingInt(a -> p[a][1]));
            for (int j = 1; j < ver[i].size(); j++) {
                int u = ver[i].get(j - 1), v = ver[i].get(j);
                addNeighbors(u, v);
            }
            hor[i].sort(Comparator.comparingInt(a -> p[a][0]));
            for (int j = 1; j < hor[i].size(); j++) {
                int u = hor[i].get(j - 1), v = hor[i].get(j);
                addNeighbors(u, v);
            }
        }

        long ans = 1;
        for (int i = 0; i < n; i++) {
            if (!used[i]) {
                uniqueX.clear();
                uniqueY.clear();
                sumDegree = 0; numNode = 0;
                dfs(i);
                long ways = mpow(2, uniqueX.size() + uniqueY.size());
                if (sumDegree / 2 == numNode - 1) ways = (ways - 1 + MOD) % MOD;
                ans = ans * ways % MOD;
            }
        }
        out.println(ans);
    }

    void dfs(int u) {
        used[u] = true;
        uniqueX.add(p[u][0]);
        uniqueY.add(p[u][1]);
        numNode++;
        sumDegree += G[u].size();
        for (int v : G[u]) {
            if (!used[v]) dfs(v);
        }
    }

    long mpow(int a, int n) {
        long res = 1;
        while (n > 0) {
            if ((n & 1) > 0) res = res * a % MOD;
            a = a * a % MOD;
            n >>= 1;
        }
        return res;
    }

    void addNeighbors(int u, int v) {
        G[u].add(v);
        G[v].add(u);
    }

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

    int lowerBound(int[] a, int k) {
        int lb = -1, ub = a.length;
        while (ub - lb > 1) {
            int m = (lb + ub) >> 1;
            if (a[m] >= k) ub = m;
            else lb = m;
        }
        return ub;
    }

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

    static FastScanner in;
    static PrintWriter out;

    static class FastScanner {
        BufferedReader in;
        StringTokenizer st;

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

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

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

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

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


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

public class E
{
    PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
    BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

    long[] fact = new long[4010];
    long[] factInv = new long[4010];
    int MOD = 998244853;

    public void go() throws IOException
    {
        StringTokenizer tok = new StringTokenizer(in.readLine());
        int n = Integer.parseInt(tok.nextToken());
        int m = Integer.parseInt(tok.nextToken());

        fact[0] = 1;
        factInv[0] = 1;
        for (int i = 1; i < fact.length; i++)
        {
            fact[i] = i * fact[i-1] % MOD;
            factInv[i] = inverse(i) * factInv[i-1] % MOD;
        }

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

        for (int i = 0; i <= n; i++)
        {
            for (int j = 0; j <= m; j++)
            {
                if (i == 0)
                {
                    zeros[i][j] = 1;
                }
                else if (i > j)
                {
                    zeros[i][j] = 0;
                }
                else
                {
                    zeros[i][j] = (zeros[i-1][j] + zeros[i][j-1]) % MOD;
                }
                // zeros[i][j] += 1;
            }
        }
        // for (long[] arr : zeros)
        // {
        //     out.println(Arrays.toString(arr));
        // }

        for (int i = 0; i <= n; i++)
        {
            for (int j = 0; j <= m; j++)
            {
                if (j == 0)
                {
                    dp[i][j] = i;
                }
                else if (i == 0)
                {
                    dp[i][j] = 0;
                }
                else
                {
                    long p1 = (dp[i-1][j] + nck(i+j-1, j)) % MOD;
                    long p2 = (dp[i][j-1] - nck(i+j-1, i) + zeros[i][j-1] + MOD) % MOD;
                    dp[i][j] = (p1 + p2) % MOD;
                }
            }
        }

        out.println(dp[n][m]);

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

    public long modPow(long n, int p)
    {
        if (p == 0)
        {
            return 1;
        }
        long pow = modPow(n*n % MOD, p/2);
        if (p % 2 == 1)
        {
            pow *= n;
            pow %= MOD;
        }
        return pow;
    }

    public long inverse(long n)
    {
        return modPow(n, MOD-2);
    }

    public long nck(int n, int k)
    {
        if (k < 0 || k > n)
        {
            return 0;
        }
        return fact[n] * (factInv[k] * factInv[n-k] % MOD) % MOD;
    }

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


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

public class codeforces2 { // in case I want to work on more than 1 problem at a time
	public static PrintWriter out;
	public static class MyScanner {
		BufferedReader br;
		StringTokenizer st;
		public MyScanner() {
			br = new BufferedReader(new InputStreamReader(System.in));
		}
		String next() {
			while (st == null || !st.hasMoreElements()) {
				try {
					st = new StringTokenizer(br.readLine());
				}
				catch (IOException e) {
					e.printStackTrace();
				}
			}
			return st.nextToken();
		}
		int nextInt() {
			return Integer.parseInt(next());
		}
		long nextLong() {
			return Long.parseLong(next());
		}
		double nextDouble() {
			return Double.parseDouble(next());
		}
		String nextLine() {
			String str = "";
			try {
				str = br.readLine();
			}
			catch (IOException e) {
				e.printStackTrace();
			}
			return str;
		}
	}
	// The next two void functions are shuffle functions on an array.
	// This way, quick sort encounters the worst case scenario with low probability.
	// A reason for doing this is if we don't a primitive data array to an object array.
	// For safety reasons, it would be preferable to use object arrays unless doing so expends a lot of time.
	public static void shuffleLongArray(long[] arr) {
		int n = arr.length;
		Random rnd = new Random();
        for (int i=0; i < n; i++) {
        	long tmp = arr[i];
        	int randomPos = i + rnd.nextInt(n-i);
        	arr[i] = arr[randomPos];
        	arr[randomPos] = tmp;
        }
	}
	public static void shuffleIntArray(int[] arr) {
		int n = arr.length;
		Random rnd = new Random();
        for (int i=0; i < n; i++) {
        	int tmp = arr[i];
        	int randomPos = i + rnd.nextInt(n-i);
        	arr[i] = arr[randomPos];
        	arr[randomPos] = tmp;
        }
	}
	public static void main (String[] args) throws IOException {
    	MyScanner sc = new MyScanner();
    	out = new PrintWriter(new BufferedOutputStream(System.out));
    	// Write solution here.
    	int[][] dp = new int[2001][2001]; // f(n,m)
    	int[][] choose = new int[2001][2001];
    	for (int i=0; i <= 2000; i++) {
    		choose[i][0] = 1;
    		choose[0][i] = 1;
    	}
    	int mega = 998244853;
    	long giga = 998244853L;
    	for (int i=1; i <= 2000; i++) {
    		for (int j=1; j <= 2000; j++) {
    			choose[i][j] = (choose[i-1][j] + choose[i][j-1]) % mega;
    		}
    	}
    	long[] catalan = new long[2001];
    	catalan[0] = 1L;
    	catalan[1] = 1L;
    	for (int i=2; i <= 2000; i++) {
    		for (int j=0; j < i; j++) {
    			catalan[i] = (catalan[i] + catalan[j]*catalan[i-j-1]) % giga;
    		}
    	}
    	int[][] change = new int[2001][2001];
    	for (int j=1; j < 2000; j++) {
    		for (int i=j+1; i <= 2000; i++) {
    			if (j==1) {
    				change[i][j] = i-1;
    			}
    			else if (i > j && j > 0) {
    				if (i == j+1) {
    					int z = (int) catalan[j];
    					change[i][j] = z;
    				}
    				else {
    					change[i][j] = (change[i][j-1] + change[i-1][j]) % mega;
    				}
    			}
    			// if (j < 10 && i < 10) out.print(change[i][j] + " ");
    		}
    		// if (j < 10) out.println();
    	}

    	for (int i=0; i <= 2000; i++) {
    		dp[i][0] = i;
    	}
    	// initialized row and column 0 successfully
    	for (int i=1; i <= 2000; i++) { // n
    		for (int j=1; j <= 2000; j++) { // m
    			dp[i][j] = dp[i][j] = (dp[i][j-1] + dp[i-1][j]) % mega;
    			if (i > j) {
    				dp[i][j] = (dp[i][j] + change[i][j]) % mega;
    			}
    		}
    	}
    	int n = sc.nextInt();
    	int m = sc.nextInt();
    	out.println(dp[n][m]);
    	out.close();
	}
}


//package round581;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

public class E {
	InputStream is;
	PrintWriter out;
	String INPUT = "1 2";

	void solve()
	{
		int mod = 998244853;
		int[][] fif = enumFIF(9000, mod);

		int n = ni(), m = ni();
		// (m,n)
		// n-m i
		// 2i-(n-m)=x-y
		// m+n = x+y
		long[] all = new long[n+2];
		for(int i = n+1;i >= 0 && i > n-m;i--){
			int x = (2*i-(n-m)+(m+n))/2;
			int y = ((m+n) - (2*i-(n-m)))/2;
			all[i] = C(m+n, n, mod, fif) - C(x+y, y, mod, fif);
		}
		long ans = 0;
		for(int i = n;i >= 0;i--){
			ans += (all[i+1] - all[i]) * i;
			ans %= mod;
		}
		if(ans < 0)ans += mod;
		out.println(ans);
	}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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