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

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

    static class HZSShufflesCards {
        NumberTheory.Mod998 mod = new NumberTheory.Mod998();
        int n;
        int m;

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

            mod.fInv(n + m);

            long phaseSize = 1;
            long p = 1;
            for (int i = 0; p != 0; i++) {
                p = mod.mult(mod.mult(p, n - i), mod.smallInv(n + m - i));
                phaseSize = mod.add(phaseSize, p);
            }

            long answer = 0;
            for (int k = 1; k <= n; k++) {
                long numPhases = mod.mult(m + k, mod.smallInv(k));
                long term = mod.mult(mod.ncr(n, k), mod.mult(numPhases, phaseSize));
                if ((k & 1) == 1)
                    answer = mod.add(answer, term);
                else
                    answer = mod.subtract(answer, term);
            }

            out.println(answer);
        }

    }

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

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

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

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

    }

    static class Util {
        public static void ASSERT(boolean assertion) {
            if (!assertion)
                throw new AssertionError();
        }

        private Util() {
        }

    }

    static class IntStack {
        int[] array;
        int size = 0;

        public IntStack() {
            this(8);
        }

        public IntStack(int capacity) {
            array = new int[capacity];
        }

        public void push(int item) {
            if (size >= array.length)
                array = resize(array);
            array[size++] = item;
        }

        public int size() {
            return size;
        }

        public int get(int i) {
            Util.ASSERT(i < size);
            return array[i];
        }

        private static int[] resize(int[] array) {
            int[] newArray = new int[array.length << 1];
            System.arraycopy(array, 0, newArray, 0, array.length);
            return newArray;
        }

        public String toString() {
            int[] trimmed = new int[size];
            System.arraycopy(array, 0, trimmed, 0, size);
            return Arrays.toString(trimmed);
        }

    }

    static class NumberTheory {
        private static void ASSERT(boolean assertion) {
            if (!assertion)
                throw new AssertionError();
        }

        public abstract static class Modulus<M extends NumberTheory.Modulus<M>> {
            final IntStack factorial = new IntStack();
            final IntStack invFactorial = new IntStack();

            public abstract long modulus();

            public Modulus() {
                super();
                factorial.push(1);
                invFactorial.push(1);
            }

            public long fact(int n) {
                while (factorial.size() <= n) {
                    factorial.push((int) mult(factorial.get(factorial.size() - 1), factorial.size()));
                }

                return factorial.get(n);
            }

            public long fInv(int n) {
                int lastKnown = invFactorial.size() - 1;

                if (lastKnown < n) {
                    long[] fInv = new long[n - lastKnown];
                    fInv[0] = inv(fact(n));
                    for (int i = 1; i < fInv.length; i++) {
                        fInv[i] = mult(fInv[i - 1], n - i + 1);
                    }
                    for (int i = fInv.length - 1; i >= 0; i--) {
                        invFactorial.push((int) fInv[i]);
                    }
                }

                return invFactorial.get(n);
            }

            public long ncr(int n, int r) {
                ASSERT(n >= 0);
                if (r < 0 || n < r)
                    return 0;
                return mult(fact(n), mult(fInv(r), fInv(n - r)));
            }

            public long smallInv(int n) {
                return mult(fInv(n), fact(n - 1));
            }

            public long normalize(long x) {
                x %= modulus();
                if (x < 0)
                    x += modulus();
                return x;
            }

            public long add(long a, long b) {
                long v = a + b;
                return v < modulus() ? v : v - modulus();
            }

            public long subtract(long a, long b) {
                long v = a - b;
                return v < 0 ? v + modulus() : v;
            }

            public long mult(long a, long b) {
                return (a * b) % modulus();
            }

            public long inv(long value) {
                long g = modulus(), x = 0, y = 1;
                for (long r = value; r != 0; ) {
                    long q = g / r;
                    g %= r;

                    long temp = g;
                    g = r;
                    r = temp;

                    x -= q * y;

                    temp = x;
                    x = y;
                    y = temp;
                }

                ASSERT(g == 1);
                ASSERT(y == modulus() || y == -modulus());

                return normalize(x);
            }

        }

        public static class Mod998 extends NumberTheory.Modulus<NumberTheory.Mod998> {
            public long modulus() {
                return 998_244_353L;
            }

        }

    }
}


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

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

class TaskE {
  static final long mult = (long) 1e6;

  public void solve(int testNumber, FastScanner in, PrintWriter out) {
    int n = in.nextInt();
    int m = in.nextInt();

    TreeSet<Long> hs = new TreeSet<Long>();
    for (int i = 0; i < m; i++) {
      int a = in.nextInt() - 1;
      int b = in.nextInt() - 1;
      hs.add(key(a, b));
    }

    if (n <= 6) {
      int e = n * (n - 1) / 2;

      boolean works = false;
      int[] a = new int[m];
      int[] b = new int[m];
      for (int i = 0; i < (1 << e) && !works; i++) {
        if (Integer.bitCount(i) != m) continue;
        int[] deg = new int[n];
        int bit = 0;
        int ii = 0;
        boolean badFlag = false;
        for (int j = 0; j < n; j++) {
          for (int k = j + 1; k < n; k++) {
            if ((i & (1 << bit)) != 0) {
              deg[j]++;
              deg[k]++;
              a[ii] = j;
              b[ii] = k;

              ii++;
              if (deg[j] > 2 || deg[k] > 2 || hs.contains(key(j, k)))
                badFlag = true;
            }
            bit++;
          }
        }

        if (!badFlag) {
          works = true;
        }
      }

      if (!works) {
        out.printf("-1\n");
      } else {
        for (int i = 0; i < m; i++) {
          out.printf("%d %d\n", a[i] + 1, b[i] + 1);
        }
      }
    } else {
      Random r = new Random();
      int runs = (int) (1e6 / n);
      for (int i = 0; i < runs; i++) {
        int[] p = new int[n];
        for (int j = 0; j < n; j++)
          p[j] = j;
        for (int j = 0; j < n - 1; j++) {
          int offSet = r.nextInt(n - j - 1) + 1;
          int k = j + offSet;
          int t = p[k];
          p[k] = p[j];
          p[j] = t;
        }
        int cnt = 0;
        for (int j = 0; j < n; j++) {
          if (!hs.contains(key(j, p[j])))
            cnt++;
        }

        if (cnt < m) continue;

        cnt = 0;
        for (int j = 0; j < n; j++) {
          if (!hs.contains(key(j, p[j]))) {
            cnt++;
            out.printf("%d %d\n", j + 1, p[j] + 1);
            if (cnt == m) return;
          }
        }
      }

      out.printf("-1\n");
    }
  }

  static long key(int a, int b) {
    if (a <= b) return a * mult + b;
    return key(b, a);
  }

}

class FastScanner {
  BufferedReader br;
  StringTokenizer st;

  public FastScanner(InputStream in) {
    br = new BufferedReader(new InputStreamReader(in));
    st = new StringTokenizer("");
  }

  public String next() {
    try {
      if (st.hasMoreTokens()) return st.nextToken();
      st = new StringTokenizer(br.readLine());
      return next();
    } catch (Exception e) {
      return "";
    }
  }

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


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

import static java.lang.Math.*;

public class Solution implements Runnable {

	public void solve () throws Exception {
		char c [] = nextToken().toCharArray();

		int n = c.length;

		int e [] = new int [n];
		for (int i = 0; i < n; i++) {
			if (c[i] == 'B') e [i] = 1;
		}

		long d [][][][][] = new long [n + 1][2][2][2][2];

		if (c[0] == 'A') {
			d[1][0][0][0][0] = 1;
			d[1][0][1][1][1] = 1;
		} else {
			d[1][0][1][0][1] = 1;
			d[1][0][0][1][0] = 1;
		}

		long res = 0;

		for (int i = 1; i < n; i++) {
			for (int first = 0; first < 2; first++) {
				for (int last = 0; last < 2; last++) {
					for (int matchedLast = 0; matchedLast < 2; matchedLast++) {
						for (int invertedFirst = 0; invertedFirst < 2; invertedFirst++) {
							if (d[i][invertedFirst][first][last][matchedLast] == 0) continue;
							if (i == 1) {
								if (last == 0) {
									// put 0
									if (e[i] != 0) {
										d[i + 1][invertedFirst][first][0][1] += d[i][invertedFirst][first][last][matchedLast];
									} else {
										d[i + 1][invertedFirst][first][0][0] += d[i][invertedFirst][first][last][matchedLast];
									}

									// put 1
									if (e[1] == 0 && first == 1) {
										d[i + 1][1][0][1][0] += d[i][invertedFirst][first][last][matchedLast];
									}

								} else {
									// put 0
									if (e[i] != 0) {
										d[i + 1][invertedFirst][first][0][1] += d[i][invertedFirst][first][last][matchedLast];
									} else {
										d[i + 1][invertedFirst][first][0][0] += d[i][invertedFirst][first][last][matchedLast];
									}
									// put 1
									if (e[i] != 1) {
										d[i + 1][invertedFirst][first][1][1] += d[i][invertedFirst][first][last][matchedLast];
									} else {
										d[i + 1][invertedFirst][first][1][0] += d[i][invertedFirst][first][last][matchedLast];
									}
								}
							} else if (i != n - 1) {
								if (matchedLast == 0) { // yes

									// put 0
									if (e[i] == 1) {
										d[i + 1][invertedFirst][first][0][1] += d[i][invertedFirst][first][last][matchedLast];
									} else {
										d[i + 1][invertedFirst][first][0][0] += d[i][invertedFirst][first][last][matchedLast];
									}

									// put 1
									if (last == 1) {
										if (e[i] == 0) {
											//d[i + 1][first][1][1] += d[i][first][last][matchedLast];
										} else {
											d[i + 1][invertedFirst][first][1][0] += d[i][invertedFirst][first][last][matchedLast];
										}
									}

								} else { // no

									// put 1
									if (last == 0 && e[i] == 0) {
										d[i + 1][invertedFirst][first][1][0] += d[i][invertedFirst][first][last][matchedLast];
									}
								}
							} else {
								if (matchedLast == 0) { // yes

									// put 0
									if (first == 0) {
										if ((e[0] == 0 && e[i] == 0 && invertedFirst == 0) || (invertedFirst == 1)) {
											res += d[i][invertedFirst][first][last][matchedLast];
										}
									} else {
										if (e[0] == 0 && e[i] == 1) {
											res += d[i][invertedFirst][first][last][matchedLast];
										}
									}

									// put 1
									if (first == 0 && last != 0 && e[i] == 1) {
										res += d[i][invertedFirst][first][last][matchedLast];
									}

								} else { // no

									// put 1
									if (first == 0 && e[i] == 0 && last == 0) {
										res += d[i][invertedFirst][first][last][matchedLast];
									}
								}
							}
						}
					}
				}
			}
		}

		out.println(res);

	}

	static final String fname = "";
	static long stime = 0;

	BufferedReader in;
	PrintWriter out;
	StringTokenizer st;

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

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

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

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

	@Override
	public void run() {
		try {
			in = new BufferedReader(new InputStreamReader(System.in));
			out = new PrintWriter(System.out);
			solve ();
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			out.close();
		}
	}

	public static void main(String[] args) {
		new Thread(null, new Solution(), "", 1<<26).start();
	}

}


import java.io.BufferedReader;
// import java.io.FileInputStream;
// import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Random;
import java.util.StringTokenizer;

import static java.lang.Math.abs;
import static java.lang.Math.max;
import static java.lang.Math.min;
import static java.lang.Math.round;
import static java.util.Arrays.copyOf;
import static java.util.Arrays.fill;
import static java.util.Arrays.sort;
import static java.util.Collections.reverseOrder;
import static java.util.Collections.sort;
import static java.util.Comparator.comparing;

public class Main {
    FastScanner in;
    PrintWriter out;

    int area(long ax, long ay, long bx, long by, long cx, long cy) {
        // удвоеная знаковая площадь треугольник abc; векторное произведение ab и ac
        long s = (bx - ax) * (cy - ay) - (by - ay) * (cx - ax);
        return s < 0 ? -1 : s > 0 ? 1 : 0;
    }

    private void solve() throws IOException {
        int n = in.nextInt();
        long[] x = new long[n], y = new long[n];
        for (int i = 0; i < n; i++) {
            x[i] = in.nextLong();
            y[i] = in.nextLong();
        }
        char[] s = in.next().toCharArray();
        boolean[] used = new boolean[n];

        int cur = 0;
        for (int i = 1; i < n; i++)
            if (y[i] < y[cur] || (y[i] == y[cur] && x[i] < x[cur]))
                cur = i;
        used[cur] = true;
        out.print(cur + 1 + " ");

        for (int i = 0; i < n - 1; i++) {
            int next = -1;
            for (int j = 0; j < n; j++)
                if (!used[j] && (next == -1 || (s[i] == 'L' && area(x[cur], y[cur], x[next], y[next], x[j], y[j]) < 0) ||
                        (s[i] == 'R' && area(x[cur], y[cur], x[next], y[next], x[j], y[j]) > 0)))
                    next = j;
            cur = next;
            used[cur] = true;
            out.print(cur + 1 + " ");
        }

        out.println();
    }

    class FastScanner {
        StringTokenizer st;
        BufferedReader br;

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

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

        boolean hasNext() throws IOException {
            return br.ready() || (st != null && st.hasMoreTokens());
        }

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

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

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

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

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

    private void run() throws IOException {
        in = new FastScanner(System.in); // new FastScanner(new FileInputStream(".in"));
        out = new PrintWriter(System.out); // new PrintWriter(new FileOutputStream(".out"));

        for (int t = 1; t-- > 0; )
            solve();

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

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


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.StringTokenizer;

public class d {
    static double EPS = 1e-6    ;
    public static void main(String[] args) {
        FS in = new FS(System.in);
        PrintWriter out = new PrintWriter(System.out);

        int n = in.nextInt();

        Vec com = new Vec(0, 0);
        Vec[] vecs = new Vec[n];
        for(int i = 0; i < n; i++) {
            com = com.add(vecs[i] = new Vec(in.nextInt(), in.nextInt()));
        }
        com = com.scaleR(n);

        boolean[] works = new boolean[n];
        Arrays.fill(works, true);
        int num = n;
        for(int i = 0; i < n; i++) {
            if(vecs[i].equals(com)) {
                works[i] = false;
                num--;
                continue;
            }
            for(int j = 0; j < i; j++) {
                if(works[j] && vecs[i].sub(com).equals(com.sub(vecs[j]))) {
                    works[i] = works[j] = false;
                    num -= 2;
                    break;
                }
            }
        }
        Vec[] act = new Vec[num];
        int curr = 0;
        for(int i = 0; i < n; i++) if(works[i]) act[curr++] = vecs[i];
        n = num;
        if(n == 0) {
            System.out.println(-1);
            return;
        }
        int res = 0;

        Vec[] norms = new Vec[n];

        outer: for(int i = 0; i < n; i++) {
            Vec diff = act[i].sub(act[0]);
            Vec mid = act[0].add(diff.scaleR(2));
            Vec perp = com.sub(mid).rot90();
            if(perp.equals(new Vec(0, 0))) continue;
            Vec norm = perp;
            norm = norm.scaleR(Math.sqrt(norm.dot(norm)));
            if(norm.x < 0 || (eq(norm.x, 0) && norm.y < 0)) {
                norm.x *= -1;
                norm.y *= -1;
            }
            norms[i] = norm;
            for(int j = 0; j < i; j++) {
                if(norms[j].equals(norm)) continue outer;
            }
            double[] arr = new double[n];
            for(int j = 0; j < n; j++) arr[j] = perp.dot(act[j]);
            Arrays.sort(arr);
            double cent = (arr[0]+arr[n-1])/2;
            for(int j = 0; j < n; j++) {
                if(!eq(cent-arr[j], arr[n-1-j]-cent)) continue outer;
            }
            res++;
        }
        System.out.println(res);
        out.close();
    }

    static class Vec {
        double x, y;

        public Vec(double A, double B) {
            x = A;
            y = B;
        }

        public Vec add(Vec o) {
            return new Vec(x+o.x, y+o.y);
        }

        public Vec sub(Vec o) {
            return new Vec(x-o.x, y-o.y);
        }

        public Vec scale(double s) {
            return new Vec(x*s, y*s);
        }

        public Vec scaleR(double s) {
            return new Vec(x/s, y/s);
        }

        public Vec rot90() {
            return new Vec(-y, x);
        }

        public double dot(Vec o) {
            return x*o.x + y*o.y;
        }

        @Override
        public boolean equals(Object o) {
            return eq(x, ((Vec)o).x) && eq(y, ((Vec)o).y);
        }
    }

    static boolean eq(double a, double b) {
        return Math.abs(a-b) <= EPS;
    }

    static class FS {
        BufferedReader in;
        StringTokenizer token;

        public FS(InputStream str) {
            in = new BufferedReader(new InputStreamReader(str));
        }

        public String next() {
            if(token == null || !token.hasMoreElements()) {
                try {
                    token = new StringTokenizer(in.readLine());
                } catch (IOException ex) {
                }
                return next();
            }
            return token.nextToken();
        }

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


import java.util.*;
//4 6 2
//1 2
//2 3
//3 4
//4 1
//1 3
//2 4

public class E {
	public static void main(String[] args) {
		Scanner s = new Scanner(System.in);
		n = s.nextInt();
		m = s.nextInt();
		k = s.nextInt();
		a = new int[m][];
		for (int i = 0; i < m; ++i) {
			int u = s.nextInt() - 1, v = s.nextInt() - 1;
			a[i] = new int[] { u, v };
		}
		b = new boolean[m];
		System.out.println(f(-1, m));
	}

	static int n, m, k;
	static int[][] a;
	static boolean[] b;

	static int f(int x, int en) {
		if (en == n - 1) {
			int[] cs = new int[n];
			for (int i = 0; i < m; ++i) {
				if (!b[i]) {
					++cs[a[i][0]];
					++cs[a[i][1]];
				}
			}
			int cnt = 0;
			for (int c : cs) {
				if (c == 1) {
					++cnt;
				}
			}
			return cnt == k ? 1 : 0;
		}
		int result = 0;
		for (int i = x + 1; i < m; ++i) {
			if (!b[i]) {
				b[i] = true;
				result += f(i, en - 1);
				b[i] = false;
			}
		}
		return result;
	}

	static int max(int... is) {
		int r = 0;
		for (int i : is)
			r = Math.max(r, i);
		return r;
	}
}


import static java.lang.Double.parseDouble;
import static java.lang.Integer.parseInt;
import static java.lang.Long.parseLong;
import static java.lang.Math.abs;
import static java.lang.Math.floorDiv;
import static java.lang.Math.max;
import static java.lang.Math.min;
import static java.lang.System.exit;
import static java.util.Arrays.fill;

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

public class G {

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

//	static final Random rng = new Random(42);
//	static boolean rngOk;

	static void solve() throws Exception {
		int n = nextInt();
		int l = nextInt();
//		int n = rng.nextInt(40) + 1;
//		int l = rng.nextInt(15) + 1;
//		long rngX[] = new long[l + 1];
//		long rngY[] = new long[l + 1];
//		for (int i = 0; i < l; i++) {
//			long dx, dy;
//			switch (rng.nextInt(4)) {
//			case 0:
//				dx = 1;
//				dy = 0;
//				break;
//			case 1:
//				dx = -1;
//				dy = 0;
//				break;
//			case 2:
//				dx = 0;
//				dy = 1;
//				break;
//			case 3:
//				dx = 0;
//				dy = -1;
//				break;
//			default:
//				throw new AssertionError();
//			}
//			rngX[i + 1] = rngX[i] + dx;
//			rngY[i + 1] = rngY[i] + dy;
//		}
		long t[] = new long[n];
		long x[] = new long[n];
		long y[] = new long[n];
		{
			long pt = 0;
			long px = 0;
			long py = 0;
			for (int i = 0; i < n; i++) {
				long ct = nextLong();
				long cx = nextLong();
				long cy = nextLong();
//				long ct = pt + rng.nextInt(40) + 1;
//				long cx = (ct / l) * rngX[l] + rngX[(int) (ct % l)];
//				long cy = (ct / l) * rngY[l] + rngY[(int) (ct % l)];
//				if (rng.nextInt(10) == 0) {
//					cx += rng.nextInt(5) - 2;
//				}
//				if (rng.nextInt(10) == 0) {
//					cy += rng.nextInt(5) - 2;
//				}
				if (ct - pt < abs(cx - px) + abs(cy - py) || ((ct ^ cx ^ cy) & 1) != 0) {
					out.print("NO");
					return;
				}
				t[i] = ct;
				x[i] = cx + cy;
				y[i] = cx - cy;
				pt = ct;
				px = cx;
				py = cy;
			}
		}
		long lt[] = new long[l + 1];
		long lx[] = new long[l + 1];
		long ly[] = new long[l + 1];
		fill(lt, -1);
		lt[0] = 0;
		lx[0] = 0;
		ly[0] = 0;
		long shiftXmin = -l;
		long shiftXmax = l;
		long shiftYmin = -l;
		long shiftYmax = l;
		for (int i = 0; i < n; i++) {
			int j = (int) (t[i] % l);
			if (lt[j] >= 0) {
				long its = (t[i] - lt[j]) / l;
				if ((x[i] - lx[j]) % its != 0 || ((y[i] - ly[j]) % its != 0)) {
					out.print("NO");
					return;
				}
				shiftXmin = max(shiftXmin, (x[i] - lx[j]) / its);
				shiftXmax = min(shiftXmax, (x[i] - lx[j]) / its);
				shiftYmin = max(shiftYmin, (y[i] - ly[j]) / its);
				shiftYmax = min(shiftYmax, (y[i] - ly[j]) / its);
			} else {
				lt[j] = t[i];
				lx[j] = x[i];
				ly[j] = y[i];
			}
		}
		lt[l] = 0;
		lx[l] = 0;
		ly[l] = 0;
//		System.err.println(Arrays.toString(lt));
//		System.err.println(Arrays.toString(lx));
//		System.err.println(Arrays.toString(ly));
		{
			int pi = 0;
			for (int i = 1; i <= l; i++) {
				if (lt[i] < 0) {
					continue;
				}
				long its = (lt[i] - lt[pi] - (i - pi)) / l;
				if (its == 0) {
					if (i - pi < abs(lx[i] - lx[pi]) || i - pi < abs(ly[i] - ly[pi])) {
						out.print("NO");
						return;
					}
				} else {
					long dx = lx[i] - lx[pi];
					long dy = ly[i] - ly[pi];
					// dx - (i - pi) <= shiftX * its
					// dx + (i - pi) >= shiftX * its
					if (its > 0) {
						shiftXmin = max(shiftXmin, floorDiv(dx - (i - pi) + its - 1,  its));
						shiftXmax = min(shiftXmax, floorDiv(dx + (i - pi), its));
						shiftYmin = max(shiftYmin, floorDiv(dy - (i - pi) + its - 1, its));
						shiftYmax = min(shiftYmax, floorDiv(dy + (i - pi), its));
					} else {
						shiftXmin = max(shiftXmin, floorDiv(dx + (i - pi) + its + 1, its));
						shiftXmax = min(shiftXmax, floorDiv(dx - (i - pi), its));
						shiftYmin = max(shiftYmin, floorDiv(dy + (i - pi) + its + 1, its));
						shiftYmax = min(shiftYmax, floorDiv(dy - (i - pi), its));
					}
				}
				pi = i;
			}
			if (((shiftXmin ^ l) & 1) != 0) {
				++shiftXmin;
			}
			if (((shiftXmax ^ l) & 1) != 0) {
				--shiftXmax;
			}
			if (((shiftYmin ^ l) & 1) != 0) {
				++shiftYmin;
			}
			if (((shiftYmax ^ l) & 1) != 0) {
				--shiftYmax;
			}
			if (shiftXmin > shiftXmax || shiftYmin > shiftYmax) {
				out.print("NO");
				return;
			}
		}
		{
			long shiftX = shiftXmin;
			long shiftY = shiftYmin;
			long cx = 0;
			long cy = 0;
			int pi = 0;
			for (int i = 1; i <= l; i++) {
				if (lt[i] < 0) {
					continue;
				}
				long its = (lt[i] - i) / l;
				long nx = lx[i] - shiftX * its;
				long ny = ly[i] - shiftY * its;
				while (pi < i) {
					boolean xUp = nx > cx;
					boolean yUp = ny > cy;
					out.print(xUp ? (yUp ? 'R' : 'U') : (yUp ? 'D' : 'L'));
					if (xUp) {
						++cx;
					} else {
						--cx;
					}
					if (yUp) {
						++cy;
					} else {
						--cy;
					}
					++pi;
				}
				if (cx != nx || cy != ny) {
//					System.err.println(n + " " + l);
//					System.err.println(Arrays.toString(rngX));
//					System.err.println(Arrays.toString(rngY));
//					System.err.println(Arrays.toString(t));
//					System.err.println(Arrays.toString(x));
//					System.err.println(Arrays.toString(y));
//					System.err.println(Arrays.toString(lt));
//					System.err.println(Arrays.toString(lx));
//					System.err.println(Arrays.toString(ly));
//					System.err.println(shiftX + " " + shiftY);
//					System.err.println(i + " " + cx + " " + cy + " " + nx + " " + ny);
					throw new AssertionError();
				}
			}
		}
//		rngOk = true;
	}

	static int nextInt() throws IOException {
		return parseInt(next());
	}

	static long nextLong() throws IOException {
		return parseLong(next());
	}

	static double nextDouble() throws IOException {
		return parseDouble(next());
	}

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

	public static void main(String[] args) {
		try {
			in = new BufferedReader(new InputStreamReader(System.in));
			out = new PrintWriter(new OutputStreamWriter(System.out));
//			if (true) while (true) {
//				rngOk = false;
//				solve();
////				if (!rngOk) {
////					throw new AssertionError();
////				}
//				System.err.println("PASS");
//			}
			solve();
			in.close();
			out.close();
		} catch (Throwable e) {
			e.printStackTrace();
			exit(1);
		}
	}
}


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

public class Main {
    public static void main(String args[]) throws Exception {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        Task solver = new Task();
        solver.main(in, out);
        out.close();
    }
}

class Task {
    final int maxn = 41111;
    ArrayList<Integer> Beg, End;
    Integer[] X, Y;
    int N, M;
    PrintStream cout = System.out;

    void print(Object[] arr) {
        cout.println("print arr :");
        for (Object i : arr) {
            cout.print(i + " ");
        }
        cout.println();
    }

    int value;
    long ans = 0;

    void update(int v, long c) {
        if (v == value) {
            ans += c;
        } else if (v > value) {
            value = v;
            ans = c;
        }
    }

    long calc(long n) {
        n = n * n - n;
        n >>= 1;
        return n;
    }

    long single(Integer[] x) {
        int n = x.length;
        int a = 0, b = 0;
        long ans = n;
        if (x[0] == x[n - 1]) {
            ans = ans * (ans - 1) * (ans - 2) / 6;
        //  cout.println(ans);
        } else {
            for (int i = 0; i < n; ++i) {
                if (x[i] == x[0])
                    ++a;
                if (x[i] == x[0])
                    ++b;
            }
            ans -= b + a;
            ans = ans * a * b;
            ans += calc(a) * b;
            ans += calc(b) * a;
        }
        return ans;
    }

    void run(Integer x[], Integer y[]) {
        int n = x.length;
        int m = y.length;
        int i, j;
        long sub = 0;
        int c = 0;
        for (i = 0, j = 0; i < n; ++i) {
            while (j < m && y[j] < x[i]) {
                ++j;
                ++c;
            }
            sub += calc(c);
        }
        c = 0;
        for (i = n - 1, j = m - 1; i >= 0; --i) {
            while (j >= 0 && y[j] > x[i]) {
                --j;
                ++c;
            }
            sub += calc(c);
        }
        sub = calc(m) * n - sub;

        update(N * 2, sub);
    }

    void main(InputReader in, PrintWriter out) throws Exception {
        Beg = new ArrayList<Integer>();
        End = new ArrayList<Integer>();
        N = in.nextInt();
        M = in.nextInt();
        for (int i = 0; i < M; ++i) {
            int t, s;
            t = in.nextInt();
            s = in.nextInt();
            if (t == 0) {
                Beg.add(s);
            } else {
                End.add(s);
            }
        }
        // out.println(Beg.size());
        X = Beg.toArray(new Integer[Beg.size()]);
        Y = End.toArray(new Integer[End.size()]);
        Arrays.sort(X);
        Arrays.sort(Y);
        // print(X);
        // print(Y);
        int n = X.length;
        int m = Y.length;
        ans = 0;
        if (m > 2) {
            update(2 * (Y[m - 1] - Y[0]), single(Y));
        }
        if (n > 2) {
            update(2 * (X[n - 1] - X[0]), single(X));
        }
        if (n > 0 && m > 0) {
            if (X[n - 1] < Y[0]) {
                update(N * 2 - (Y[0] - X[n - 1]), m + n - 2);
            } else if (X[0] > Y[m - 1]) {
                update(N * 2 - (X[0] - Y[m - 1]), m + n - 2);
            } else {
                run(X, Y);
                run(Y, X);
            }
        }
        out.println(ans);

    }
}

class InputReader {
    BufferedReader reader;
    StringTokenizer tokenizer;

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

    String next() {
        if (!hasNext())
            throw new RuntimeException();
        return tokenizer.nextToken();
    }

    boolean hasNext() {
        while (tokenizer == null || !tokenizer.hasMoreTokens())
            try {
                tokenizer = new StringTokenizer(reader.readLine());
            } catch (Exception e) {
                return false;
            }
        return true;
    }

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

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


import java.util.List;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.ArrayList;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Random;
import java.util.StringTokenizer;
import java.math.BigInteger;
import java.util.Collections;
import java.io.InputStream;

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

class TaskE {
    static Random r = new Random(3731L);

    public void solve(int testNumber, InputReader in, PrintWriter out) {

        int n = in.nextInt();
        int m = in.nextInt();
        Point3D[] spheres = new Point3D[n];
        for (int i = 0; i < n; ++i) {
            spheres[i] = new Point3D(in);
        }
        for (int i = 0; i < m; ++i) {
            double a = in.nextDouble();
            double b = in.nextDouble();
            double c = in.nextDouble();
            Plane3D plane = new Plane3D(a, b, c, 0);
            Point3D[] p = new Point3D[n];
            for (int j = 0; j < n; ++j) {
                double t = -(plane.d + plane.a * spheres[j].x + plane.b * spheres[j].y + plane.c * spheres[j].z) /
                        (DoubleUtils.sqr(plane.a) + DoubleUtils.sqr(plane.b) + DoubleUtils.sqr(plane.c));
                p[j] = new Point3D(spheres[j].x + plane.a * t, spheres[j].y + plane.b * t, spheres[j].z + plane.c * t);
//                p[j] = Geometry3DUtils.getProjectionOnPlane(spheres[j], plane);
            }

            rotation(a, b, c, p);
            List<Point> points = new ArrayList<Point>();
            for (int j = 0; j < n; ++j) {
                points.add(new Point(p[j].x, p[j].y));
            }

            double best = 1e100;
            for (int iter = 0; iter < 100; ++iter) {
                Point ce = solve1(points);
                double res = 0;
                for (Point po : points) {
                    res = Math.max(res, po.distanceTo(ce));
                }
                if (DoubleUtils.compareTo(best, res) > 0) {
                    best = res;
                }
            }
            out.println(best);
        }
    }

    Point solve1(List<Point> p) {
        Collections.shuffle(p, r);
        if (p.size() == 1) {
            return p.get(0);
        } else {
            double r = p.get(0).distanceTo(p.get(1)) / 2;
            Point c = p.get(0).add(p.get(1)).div(2);
            for (int j = 2; j < p.size(); ++j) {
                if (DoubleUtils.compareTo(p.get(j).distanceTo(c), r) > 0) {
                    c = solve2(p.subList(0, j), p.get(j));
                    r = c.distanceTo(p.get(j));
                }
            }
            return c;
        }
    }

    Point solve2(List<Point> p, Point po) {
        Collections.shuffle(p, r);
        double r = p.get(0).distanceTo(po);
        Point c = p.get(0).add(po).div(2);
        for (int i = 1; i < p.size(); ++i) {
            if (DoubleUtils.compareTo(p.get(i).distanceTo(c), r) > 0) {
                c = solve3(p.subList(0, i), p.get(i), po);
                r = c.distanceTo(po);
            }
        }
        return c;
    }

    Point solve3(List<Point> p, Point po, Point po2) {
        Collections.shuffle(p, r);
        double r = po.distanceTo(po2);
        Point c = po.add(po2).div(2);
        for (int i = 1; i < p.size(); ++i) {
            if (DoubleUtils.compareTo(p.get(i).distanceTo(c), r) > 0) {
                Circle cc = new Circle(po, po2, p.get(i));
                c = cc.center;
                r = c.distanceTo(po2);
            }
        }
        return c;
    }

    private void rotation(double a, double b, double c, Point3D[] p) {
        double angle = Math.PI / 2 - Math.atan2(c, b);
        double tempB = b;
        double tempC = c;
        c = Math.cos(angle) * tempC + Math.sin(angle) * tempB;
        b = -Math.sin(angle) * tempC + Math.cos(angle) * tempB;

        for (Point3D point : p) {
            double ty = point.y;
            double tz = point.z;
            point.z = Math.cos(angle) * tz + Math.sin(angle) * ty;
            point.y = -Math.sin(angle) * tz + Math.cos(angle) * ty;

        }

        angle = Math.PI / 2 - Math.atan2(c, a);
        double tempA = a;
        tempC = c;
        c = Math.cos(angle) * tempC + Math.sin(angle) * tempA;
        a = -Math.sin(angle) * tempC + Math.cos(angle) * tempA;

        for (Point3D point : p) {
            double tx = point.x;
            double tz = point.z;
            point.z = Math.cos(angle) * tz + Math.sin(angle) * tx;
            point.x = -Math.sin(angle) * tz + Math.cos(angle) * tx;
        }
    }
}

class InputReader {
    private BufferedReader reader;
    private StringTokenizer stt;

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

    public String nextLine() {
        try {
            return reader.readLine();
        } catch (IOException e) {
            return null;
        }
    }

    public String nextString() {
        while (stt == null || !stt.hasMoreTokens()) {
            stt = new StringTokenizer(nextLine());
        }
        return stt.nextToken();
    }

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

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

}

class Point3D implements Comparable<Point3D> {
    public double x;
    public double y;
    public double z;

    public String toString() {
        StringBuilder b = new StringBuilder();
        b.append('(').append(x).append(',').append(y).append(',').append(z).append(')');
        return b.toString();
    }

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

    public Point3D(InputReader in) {
        this.x = in.nextDouble();
        this.y = in.nextDouble();
        this.z = in.nextDouble();
    }

    public int compareTo(Point3D o) {
        if (DoubleUtils.compareTo(x, o.x) != 0) {
            return DoubleUtils.compareTo(x, o.x);
        }
        if (DoubleUtils.compareTo(y, o.y) != 0) {
            return DoubleUtils.compareTo(y, o.y);
        }
        return DoubleUtils.compareTo(z, o.z);
    }
}

class Plane3D {
    public double a, b, c, d;

    public Plane3D(double a, double b, double c, double d) {
        this.a = a;
        this.b = b;
        this.c = c;
        this.d = d;
    }

}

class DoubleUtils {
    public static final double EPS = 1e-8;

    public static double sqr(double x) {
        return x * x;
    }

    public static int compareTo(double a, double b) {
        if (doubleEqual(a, b)) {
            return 0;
        }
        if (a < b) {
            return -1;
        }
        return 1;
    }

    private static boolean doubleEqual(double a, double b) {
        return Math.abs(a - b) < EPS;
    }

    public static double sqrt(double a) {
        if (compareTo(a, 0) < 0) {
            System.exit(1);
        }
        if (a < 0) return 0;
        return Math.sqrt(a);
    }

    public static double hypot(double a, double b) {
        return sqrt(sqr(a) + sqr(b));
    }
}

class Point implements Comparable<Point> {
    public double x, y;

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

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

    public boolean equals(Object o) {
        Point p = (Point) o;
        return DoubleUtils.compareTo(x, p.x) == 0 && DoubleUtils.compareTo(y, p.y) == 0;
    }

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

    public Point add(Point p) {
        return new Point(x + p.x, y + p.y);
    }

    public Point sub(Point p) {
        return new Point(x - p.x, y - p.y);
    }

    public Point div(double k) {
        return new Point(x / k, y / k);
    }

    public double dotProduct(Point p) {
        return x * p.x + y * p.y;
    }

    public double length() {
        return DoubleUtils.sqrt(dotProduct(this));
    }

    public double distanceTo(Point p) {
        return sub(p).length();
    }

    /*public double distanceToLine(Line l) {
        if (l.hasPoints()) {
            return distanceToLine(l.p1, l.p2);
        }
        Line normLine = l.norm();
        return normLine.a * x + normLine.b * y + normLine.c;
    } */

    // Rotate 90 degrees clockwise (positive direction).
    Point rotate() {
        return new Point(-y, x);
    }

    public int compareTo(Point o) {
        int temp = DoubleUtils.compareTo(x, o.x);
        if (temp == 0) {
            return DoubleUtils.compareTo(y, o.y);
        }
        return temp;
    }
}

class Circle {
    public final Point center;
    public final double radius;

    public Circle(Point p1, Point p2, Point p3) {
        Point middle12 = p1.add(p2).div(2);
        Point middle23 = p2.add(p3).div(2);
        Point v12 = p2.sub(p1).rotate();
        Point v23 = p3.sub(p2).rotate();
        Point p12 = middle12.add(v12);
        Point p23 = middle23.add(v23);
        Line l1 = new Line(middle12, p12);
        Line l2 = new Line(middle23, p23);

        if (l1.intersect(l2) == null) {
            Point A = p1;
            Point B = p2;
            if (DoubleUtils.compareTo(A.distanceTo(B), p1.distanceTo(p3)) < 0) {
                A = p1;
                B = p3;
            }
            if (DoubleUtils.compareTo(A.distanceTo(B), p2.distanceTo(p3)) < 0) {
                A = p2;
                B = p3;
            }
            center = A.add(B).div(2);
            radius = center.distanceTo(A);
            return;
            //throw new AssertionError("Points on same line!");
        }
        center = l1.intersect(l2);
        radius = center.distanceTo(p1);
    }

}

class Line {
    public final double a;
    public final double b;
    public final double c;
    boolean hasPoints;

    public Line(double a, double b, double c) {
        double h = DoubleUtils.hypot(a, b);
        this.a = a / h;
        this.b = b / h;
        this.c = c / h;
        hasPoints = false;
    }

    public Line(Point p1, Point p2) {
        a = p2.y - p1.y;
        b = p1.x - p2.x;
        c = -(p1.x * a + p1.y * b);
        new Line(a, b, c);
        hasPoints = true;
    }

    public Point intersect(Line other) {
        if (parallel(other)) {
            return null;
        }
        double determinant = b * other.a - a * other.b;
        double x = (c * other.b - b * other.c) / determinant;
        double y = (a * other.c - c * other.a) / determinant;
        return new Point(x, y);
    }

    public boolean parallel(Line other) {
        return DoubleUtils.compareTo(Math.abs(a * other.b - b * other.a), 0) == 0;
    }

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

        Line line = (Line) o;

        if (!parallel(line)) return false;
        if (Math.abs(a * line.c - c * line.a) > DoubleUtils.EPS || Math.abs(b * line.c - c * line.b) > DoubleUtils.EPS) return false;

        return true;
    }
}


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

public class Main {

    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);
        // input
        int n = sc.nextInt();
        int m = sc.nextInt();
        int[][] matrix = new int[n][m];
        int k = sc.nextInt();
        for(int i = 0; i < k; ++i) {
            int x1 = sc.nextInt();
            int y1 = sc.nextInt();
            int x2 = sc.nextInt();
            int y2 = sc.nextInt();
            for(int x = x1; x <= x2; ++x) {
                for(int y = y1; y <= y2; ++y) {
                    matrix[x-1][y-1] = -1;
                }
            }
        }

        // computation: dynamic programming in matrix
        // value of n, m is 1
        // if getTopRight is blocked, value is sum of getTop and getRight
        // else value is maximum of getTop and getRight
        if(matrix[n - 1][m - 1] != -1) {
            matrix[n - 1][m - 1] = 1;
            for(int y = m - 1; y >= 0; --y) {
                for(int x = n - 1; x >= 0; --x) {
                    if(x == n - 1 && y == m - 1) {
                        matrix[x][y] = 1;
                    } else if(x == n - 1 || matrix[x+1][y] == 0) {
                        if(matrix[x][y] != -1) {
                            matrix[x][y] = Math.max(matrix[x][y + 1], 0);
                        } else {
                            matrix[x][y] = 0;
                        }
                    } else if(y == m - 1 || matrix[x][y+1] == 0) {
                        if(matrix[x][y] != -1) {
                            matrix[x][y] = Math.max(matrix[x + 1][y], 0);
                        } else {
                            matrix[x][y] = 0;
                        }
                    } else {
                        if(matrix[x][y] != -1) {
                            matrix[x][y] = matrix[x+1][y] + matrix[x][y+1] - matrix[x+1][y+1];
                        } else {
                            matrix[x][y] = 0;
                        }
                    }
                }
            }
        }
        /*for(int y = m - 3; y >= 0; y--) {
            for(int x = 0; x < n; x++) {
                System.out.print(matrix[x][y] + " ");
            }
            System.out.println();
        }*/

        System.out.println(matrix[0][0]);

    }
}


import java.util.*;
import java.io.*;
public class Edu104F{
	public static void main(String[] main) throws Exception{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		PrintWriter out = new PrintWriter(System.out);
		String s = st.nextToken();
		int[] num = new int[s.length()+1];
		num[1] = s.charAt(0) - 48;
		for(int i = 2; i <= s.length(); i++) {
			num[i] = s.charAt(i-1) - s.charAt(i-2);
		}
		int iters = 0;
		boolean edit = true;
		int min = 10000;
		while(edit) {
			iters++;
			edit = false;
			for(int i = 1; i < s.length(); i++) {
				if(num[i] > 5) {
					num[i-1]++;
					num[i] = num[i]-10;
					num[s.length()]--;
					edit = true;
				}
				else if(num[i] == 5 && num[i-1] < 0) {
					num[i-1]++;
					num[i] = num[i]-10;
					num[s.length()]--;
					edit = true;
				}
				else if(i >= 2 && num[i] == 5 && num[i-1] == 4 && num[i-2] < 0 && (num[s.length()] > 0 || num[s.length()] <= -4)) {
					num[i-2]++;
					num[i-1] = -5;
					num[i] = -5;
					num[s.length()]-=2;
					edit = true;
				}
				else if(i >= 2 && num[i] == 5 && num[i-1] == 4 && num[i-2] < 0 && num[s.length()] < -3 && num[s.length() - 1] > 0) {
					num[i-2]++;
					num[i-1] = -5;
					num[i] = -5;
					num[s.length()]-=2;
					edit = true;
				}
				else if(num[i] == 5 && num[i-1] == 5 && num[s.length()] > 1) {
					num[i-2]++;
					num[i-1] = -4;
					num[i] = -5;
					num[s.length()]-=2;
					edit = true;
				}
				else if(num[i] == 5 && num[i-1] == 5 && num[i-2] == 5) {
					num[i-2]++;
					num[i-1] = -4;
					num[i] = -5;
					num[s.length()]-=2;
					edit = true;
				}
				else if(num[i] < -5) {
					num[i-1]--;
					num[i] = num[i]+10;
					num[s.length()]++;
					edit = true;
				}
				else if(num[i] == -5 && num[i-1] > 0) {
					num[i-1]--;
					num[i] = num[i]+10;
					num[s.length()]++;
					edit = true;
				}
				else if(i >= 2 && num[i] == -5 && num[i-1] == -4 && (num[i-2] > 0 || num[i-2] == -4) && (num[s.length()] < 0 || num[s.length()] >= 4)) {
					num[i-2]--;
					num[i-1] = 5;
					num[i] = 5;
					num[s.length()]+=2;
					edit = true;
				}
				else if(i >= 2 && num[i] == -5 && num[i-1] == -4 && num[i-2] > 0 && num[s.length()] > 3 && num[s.length() - 1] < 0) {
					num[i-2]--;
					num[i-1] = 5;
					num[i] = 5;
					num[s.length()]+=2;
					edit = true;
				}
				else if(num[i] == -5 && num[i-1] == -5 && num[s.length()] < -1) {
					num[i-2]--;
					num[i-1] = 4;
					num[i] = 5;
					num[s.length()]+=2;
					edit = true;
				}
				else if(num[i] == -5 && num[i-1] == -5 && num[i-2] == -5) {
					num[i-2]--;
					num[i-1] = 4;
					num[i] = 5;
					num[s.length()]+=2;
					edit = true;
				}
			}
			if(num[s.length()] > 6) {
				num[s.length()-1]++;
				num[s.length()] -= 11;
				edit = true;
			}
			else if(num[s.length()] >= 5 && num[s.length() - 1] < 0) {
				num[s.length()-1]++;
				num[s.length()] -= 11;
				edit = true;
			}
			else if(s.length() >= 2 && num[s.length()] == 6 && num[s.length()-1] == 4 && num[s.length()-2] < 0) {
				num[s.length()-1]++;
				num[s.length()] -= 11;
				edit = true;
			}
			else if(num[s.length()] < -6) {
				num[s.length()-1]--;
				num[s.length()] += 11;
				edit = true;
			}
			else if(num[s.length()] <= -5 && num[s.length() - 1] > 0) {
				num[s.length()-1]--;
				num[s.length()] += 11;
				edit = true;
			}
			else if(s.length() >= 2 && num[s.length()] == -6 && num[s.length()-1] == -4 && num[s.length()-2] > 0) {
				num[s.length()-1]--;
				num[s.length()] += 11;
				edit = true;
			}
			int ans = 0;
			for(int i = 0; i <= s.length(); i++) {
				//out.print(num[i] + " ");
				ans += (s.length() + 1 - i)*Math.abs(num[i]);
			}
			min = Math.min(ans, min);
			if(iters > 7000000)
				break;
		}
		int ans = 0;
		for(int i = 0; i <= s.length(); i++) {
			//out.print(num[i] + " ");
			ans += (s.length() + 1 - i)*Math.abs(num[i]);
		}
		out.println(Math.min(min,ans));
		out.close();
	}
}


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

public class Mixture {

    static long[] favorite = new long[3];
    static long[][] matrix = new long[3][3];

    static void add(int to, int from) {
        for (int j = 0; j <= 2; j++) {
            matrix[to][j] += matrix[from][j];
        }
    }

    static void subtract(int to, int from) {
        for (int j = 0; j <= 2; j++) {
            matrix[to][j] -= matrix[from][j];
        }
    }

    static void reduce(int a, int b) {
        while (favorite[a] != 0L && favorite[b] != 0L) {
            if (favorite[a] >= favorite[b]) {
                favorite[a] -= favorite[b];
                subtract(a, b);
            } else {
                favorite[b] -= favorite[a];
                subtract(b, a);
            }
        }
        if (favorite[a] != 0L) {
            favorite[b] += favorite[a];
            add(b, a);
            favorite[a] -= favorite[b];
            subtract(a, b);
        }
    }

    public static void main(String[] args) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer tokenizer = new StringTokenizer(in.readLine());
        for (int j = 0; j <= 2; j++) {
            favorite[j] = Long.parseLong(tokenizer.nextToken());
            matrix[j][j] = 1L;
        }
        reduce(0, 1);
        reduce(1, 2);
        /*for (int y = 0; y <= 2; y++) {
            for (int x = 0; x <= 2; x++) {
                System.out.print(matrix[y][x] + " ");
            }
            System.out.println();
        }*/
        int amt00 = 0;
        int amtPosInfty = 0;
        int amtNegInfty = 0;
        int amtMatch = 0;
        TreeMap<Rational, Integer> positive = new TreeMap<>();
        TreeMap<Rational, Integer> negative = new TreeMap<>();
        int j = 0;
        int n = Integer.parseInt(in.readLine());
        long[] xs = new long[n + 1];
        long[] ys = new long[n + 1];
        StringBuilder out = new StringBuilder();
        for (; n > 0; n--) {
            tokenizer = new StringTokenizer(in.readLine());
            if (tokenizer.nextToken().charAt(0) == 'A') {
                j++;
                for (int a = 0; a <= 2; a++) {
                    long k = Long.parseLong(tokenizer.nextToken());
                    xs[j] += matrix[0][a] * k;
                    ys[j] += matrix[1][a] * k;
                }
                if (xs[j] == 0L) {
                    if (ys[j] == 0L) {
                        amt00++;
                    } else if (ys[j] > 0L) {
                        amtPosInfty++;
                    } else {
                        amtNegInfty++;
                    }
                } else {
                    Rational q = new Rational(ys[j], xs[j]);
                    if (xs[j] > 0L) {
                        if (positive.compute(q, (__, prev) -> prev == null ? 1 : (prev + 1)) == 1 && negative.containsKey(q)) {
                            amtMatch++;
                        }
                    } else {
                        if (negative.compute(q, (__, prev) -> prev == null ? 1 : (prev + 1)) == 1 && positive.containsKey(q)) {
                            amtMatch++;
                        }
                    }
                }
            } else {
                int j2 = j;
                j = Integer.parseInt(tokenizer.nextToken());
                if (xs[j] == 0L) {
                    if (ys[j] == 0L) {
                        amt00--;
                    } else if (ys[j] > 0L) {
                        amtPosInfty--;
                    } else {
                        amtNegInfty--;
                    }
                } else {
                    Rational q = new Rational(ys[j], xs[j]);
                    if (xs[j] > 0L) {
                        if (positive.compute(q, (__, prev) -> prev == 1 ? null : (prev - 1)) == null && negative.containsKey(q)) {
                            amtMatch--;
                        }
                    } else {
                        if (negative.compute(q, (__, prev) -> prev == 1 ? null : (prev - 1)) == null && positive.containsKey(q)) {
                            amtMatch--;
                        }
                    }
                }
                j = j2;
            }
            if (amt00 > 0) {
                out.append(1);
            } else if (amtMatch > 0 || (amtPosInfty > 0 && amtNegInfty > 0)) {
                out.append(2);
            } else {
                boolean exists = false;
                if (positive.size() >= 2) {
                    Rational q = negative.ceilingKey(positive.firstKey());
                    if (q != null && q.compareTo(positive.lastKey()) <= 0) {
                        exists = true;
                    }
                }
                if (!exists && negative.size() >= 2) {
                    Rational q = positive.ceilingKey(negative.firstKey());
                    if (q != null && q.compareTo(negative.lastKey()) <= 0) {
                        exists = true;
                    }
                }
                if (!exists && amtPosInfty > 0 && !positive.isEmpty() && !negative.isEmpty()) {
                    Rational q = positive.firstKey();
                    Rational r = negative.lastKey();
                    if (q.compareTo(r) < 0) {
                        exists = true;
                    }
                }
                if (!exists && amtNegInfty > 0 && !positive.isEmpty() && !negative.isEmpty()) {
                    Rational q = positive.lastKey();
                    Rational r = negative.firstKey();
                    if (q.compareTo(r) > 0) {
                        exists = true;
                    }
                }
                if (exists) {
                    out.append(3);
                } else {
                    out.append(0);
                }
            }
            out.append('\n');
        }
        System.out.print(out);
    }

    static class Rational implements Comparable<Rational> {
        final long num;
        final long denom;

        Rational(long num, long denom) {
            if (denom > 0L) {
                this.num = num;
                this.denom = denom;
            } else {
                this.num = -num;
                this.denom = -denom;
            }
        }

        @Override
        public int compareTo(Rational other) {
            long d = (num * other.denom) - (other.num * denom);
            if (d > 0L) {
                return 1;
            } else if (d == 0L) {
                return 0;
            } else {
                return -1;
            }
        }
    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        Scanner in = new Scanner(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskC solver = new TaskC();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskC {
        static long MOD = (long) 1e9 + 7;
        static long[] fac;
        static long[] ifac;
        static long[] inv;

        static {
            int N = (int) 1e6;
            inv = new long[N + 1];
            fac = new long[N + 1];
            ifac = new long[N + 1];
            inv[1] = 1;
            for (int i = 2; i <= N; ++i) {
                inv[i] = inv[(int) MOD % i] * (-MOD / i + MOD) % MOD;
            }
            fac[0] = ifac[0] = 1;
            for (int i = 1; i <= N; ++i) {
                fac[i] = fac[i - 1] * i % MOD;
                ifac[i] = ifac[i - 1] * inv[i] % MOD;
            }
        }

        public void solve(int testNumber, Scanner in, PrintWriter out) {
            int n = in.nextInt(), k = in.nextInt();
            long ans = 0;
            long[] a = new long[n + 1];
            long[] s = new long[n + 1];
            for (int i = k + 1; i <= n; i++) {
                a[i] = (s[i - 1] - s[i - k - 1] + i - k - 1 + MOD) * inv[i - 1] % MOD;
                s[i] = (s[i - 1] + a[i]) % MOD;
                ans = (ans + a[i] * inv[i]) % MOD;
            }
            out.print(fac[n - 1] * s[n] % MOD);
        }

    }
}


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

public class E implements Runnable {
	public static void main (String[] args) {new Thread(null, new E(), "_cf", 1 << 28).start();}

	int n;
	int MAX = 51;
	HashMap<Integer, Integer>[] dp;

	public void run() {
		FastScanner fs = new FastScanner();
		PrintWriter out = new PrintWriter(System.out);
		System.err.println("Go!");

		int a = fs.nextInt(), b = fs.nextInt();
		n = fs.nextInt();

		dp = new HashMap[MAX];
		for(int i = 0; i < MAX; i++) dp[i] = new HashMap<Integer, Integer>();

		int ret = solve(b, a);
		if(ret == 1) System.out.println("Masha");
		else if(ret == 0) System.out.println("Missing");
		else System.out.println("Stas");

		out.close();
	}

	//returns -1 if whoever is playing here loses
	//returns 1 otherwise
	int solve(int a, int b) {
		if(a >= MAX) { //draw
			return 0;
		}
		if(dp[a].containsKey(b)) return dp[a].get(b);

		boolean canDraw = false;
		if(!isBad(a, b + 1)) { //increase number of boxes
			int ret = solve(a, b + 1);
			if(ret == -1) { //i win
				dp[a].put(b, 1);
				return 1;
			}
			canDraw |= ret == 0;
		}

		if(!isBad(a + 1, b)) { //increase number of items
			int ret = solve(a + 1, b);
			if(ret == -1) {
				dp[a].put(b, 1);
				return 1;
			}
			canDraw |= ret == 0;
		}

		int ret = -1;
		if(canDraw) ret = 0;

		dp[a].put(b, ret);
		return ret;
	}

	boolean isBad(int a, int b) {
		double one = a * Math.log(b);
		double two = Math.log(n);
		return one > two || Math.abs(one-two) < 1e-9;
	}

	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) throws FileNotFoundException {
			in = new BufferedInputStream(new FileInputStream(new File(s)), 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.util.Scanner;

public class Probnik {

	public static Scanner in = new Scanner(System.in);
	public static void main(String[] args) {

		int a = in.nextInt();
		int b = in.nextInt();
		System.out.println(6-(a+b));
	}

}


import java.util.*;
import static java.lang.Math.*;

public class F {
	public static void main(String[] args) throws Exception{
		Scanner in = new Scanner(System.in);
		st = new Point(in.nextDouble(), in.nextDouble());
		en = new Point(in.nextDouble(), in.nextDouble());
		N = in.nextInt();
		T = new Tank[N];
		for(int i = 0; i < N;i++)
			T[i] = new Tank(in.nextDouble(), in.nextDouble(), in.nextDouble(), in.nextDouble());

		K = in.nextInt();

		en = en.sub(st);
		for(Tank t:T)
			t.p = t.p.sub(st);
		st = st.sub(st);

		double ang = en.ang();
		st = st.rot(-ang);
		en = en.rot(-ang);
		for(Tank t:T){
			t.p = t.p.rot(-ang);
			t.a = normang(t.a-ang);
		}

		for(Tank t:T){
			if(t.p.y > 0){
				t.p.y = -t.p.y;
				t.a = normang(2*PI-t.a);
			}
		}

		X = en.x;
		double low = 0;
		double high = Long.MAX_VALUE;
		for(int i = 0; i < 100;i++){
			double mid = (low+high)/2;
			if(safe(mid)){
				high = mid;
			}else{
				low = mid;
			}
		}
		System.out.format("%.015f\n", low);
	}
	private static boolean safe(double v) {
		int hit = 0;
		Line l = new Line(st, en);
		for(Tank t:T){
			double toend = abs(angdiff(en.sub(t.p).ang(), t.a))/t.w;
			if(toend <= X/v){
				hit++;
				continue;
			}
			double dist = pointlinedist(t.p, l);
			if(dist > v)
				continue;

			double theta1 = asin(sqrt(dist/v));
			double theta2 = PI-theta1;
			if(!EQ(sin(theta1), sqrt(dist/v)) || !EQ(sin(theta2), sqrt(dist/v)))
				throw new RuntimeException();

			double x1 = t.p.x + dist*cos(theta1)/sin(theta1);
			double t1 = abs(angdiff(theta1, t.a))/t.w;
			if(0 <= x1 && x1 <= X && t1 <= x1/v){
				hit++;
				continue;
			}

			double x2 = t.p.x + dist*cos(theta2)/sin(theta2);
			double t2 = abs(angdiff(theta2, t.a))/t.w;
			if(0 <= x2 && x2 <= X && t2 <= x2/v){
				hit++;
				continue;
			}

		}
		return hit <= K;
	}
	static int N, K;
	static Tank[] T;
	static Point st, en;
	static double X;
	static class Tank{
		Point p;
		double a, w;
		public Tank(double x, double y, double a, double w){
			p = new Point(x, y);
			this.a = a;
			this.w = w;
		}
	}

	static double eps = 1e-9;
	static boolean EQ(double a, double b){return abs(a-b) < eps;}
	static double SQ(double d){return d*d;}
	static double normang(double t){ return ((t % (2*PI)) + 2*PI) % (2*PI); }
	static double angdiff(double t1, double t2){ return normang(t1 - t2 + PI) - PI; }
	static ArrayList<Point> makeVec(Point...P){
		ArrayList<Point> ans = new ArrayList<Point>();
		for(Point p:P)
			ans.add(p);
		return ans;
	}
	static class Point{
		double x, y;
		public Point(double x, double y){this.x = x;this.y = y;}
		Point add(Point p){return new Point(x+p.x, y+p.y);}
		Point sub(Point p){return new Point(x-p.x, y-p.y);}
		Point mult(double d){return new Point(x*d, y*d);}
		double dot(Point p){return x*p.x+ y*p.y;}
		double cross(Point p){return x*p.y - y*p.x;}
		double len(){return hypot(x, y);}
		Point scale(double d){return mult(d/len());}
		double dist(Point p){return sub(p).len();}
		double ang(){return atan2(y, x);}
		static Point polar(double r, double theta){return new Point(r*cos(theta), r*sin(theta));}
		Point rot(double theta){return new Point(x*cos(theta)-y*sin(theta), x*sin(theta)+y*cos(theta));}
		Point perp(){return new Point(-y, x);}
		boolean equals(Point p){return EQ(0, dist(p));}
		double norm(){return dot(this);}
		public String toString(){return String.format("(%.03f, %.03f)", x, y);}
	}
	static class Line{
		Point a, b;
		Line(Point a, Point b){this.a = a;this.b = b;}
		public String toString(){return String.format("{%s -> %s}", a, b);}
	}
	static class Circle{
		Point p;double r;
		public Circle(Point p, double r){this.p = p;this.r = r;}
		public Circle(Point a, Point b, Point c){
			Point p1 = a.add(b).mult(0.5);
			Line l1 = new Line(p1, p1.add(a.sub(b).perp()));
			Point p2 = b.add(c).mult(0.5);
			Line l2 = new Line(p2, p2.add(b.sub(c).perp()));
			p = lineline(l1, l2);
			assert(p != null);
			r = p.dist(a);
		}
	}
	static double ccw(Point p1, Point p2, Point p3){
		return p2.sub(p1).cross(p3.sub(p1));
	}
	static Point lineline(Line a, Line b){//tested
		double d = a.b.sub(a.a).cross(b.b.sub(b.a));
		if(EQ(d, 0))
			return null;
		return a.a.add((a.b.sub(a.a)).mult(b.b.sub(b.a).cross(a.a.sub(b.a))/d));
	}
	static Point segline(Line a, Line b){
		Point inter = lineline(a, b);
		if(inter == null || !onseg(a, inter))
			return null;
		return inter;
	}
	static Point segseg(Line a, Line b){//tested
		Point inter = lineline(a, b);
		if(inter == null || !onseg(a, inter) || !onseg(b, inter))
			return null;
		return inter;
	}
	static boolean onseg(Line l, Point p){ //tested
		Point delta = l.b.sub(l.a);
		return online(l, p) && delta.dot(l.a)-eps <= delta.dot(p) && delta.dot(p) <= delta.dot(l.b)+eps;
	}
	static boolean online(Line l, Point p){ //tested
		return EQ(ccw(l.a, l.b, p), 0);
	}
	static Point pointline(Point p, Line l){
		Point v = l.b.sub(l.a).scale(1);
		double dot = p.sub(l.a).dot(v);
		return l.a.add(v.mult(dot));
	}
	static Point pointseg(Point p, Line l){
		Point v = l.b.sub(l.a).scale(1);
		double dot = p.sub(l.a).dot(v);
		dot = max(dot, 0);
		dot = min(dot, l.b.dist(l.a));
		return l.a.add(v.mult(dot));
	}
	static double pointsegdist(Point p, Line l){
		return pointseg(p, l).dist(p);
	}
	static double pointlinedist(Point p, Line l){
		return pointline(p, l).dist(p);
	}

	static double polyarea(Point[] poly){
		double area = 0;
		for(int i = 0; i < poly.length; i++)
			area += poly[i].cross(poly[(i+1)%poly.length]);
		return abs(area)/2.0;
	}
	static int pointinpoly(Point[] poly, Point p){
		double ang = 0.0;
		for(int i = 0; i < poly.length; i++){
			Point a = poly[i];
			Point b = poly[(i+1)%poly.length];
			if(onseg(new Line(a, b), p))
				return 0;
			ang += angdiff(a.sub(p).ang(), b.sub(p).ang());
		}
		return EQ(ang, 0) ? -1 : 1;
	}

	static Point v0;
	static ArrayList<Point> convexhull(ArrayList<Point> P){//tested
		v0 = null;
		for(Point p:P)
			if(v0 == null || p.x < v0.x - eps || (EQ(p.x, v0.x) && p.y < v0.y))
				v0 = p;
		Collections.sort(P, new Comparator<Point>(){
			public int compare(Point a, Point b){
				if(a == v0) return -1;
				if(b == v0) return 1;
				double ccw = ccw(v0, a, b);
				if(EQ(ccw, 0)){
					double d1 = v0.dist(a);
					double d2 = v0.dist(b);
					if(d1 < d2) return -1;
					if(d1 > d2) return 1;
					return 0;
				}
				return (int) -signum(ccw);
			}});
		ArrayList<Point> ch = new ArrayList<Point>();
		for(Point p:P){
			while(ch.size() >= 2 && ccw(ch.get(ch.size()-2), ch.get(ch.size()-1), p) <= 0)
				ch.remove(ch.size()-1);
			ch.add(p);
		}
		return ch;
	}
	//add half space intersection

	//circle
	static ArrayList<Point> circline(Circle c, Line l){
		Point x = pointline(c.p, l);
		double d = x.dist(c.p);
		if(d > c.r + eps) return new ArrayList<Point>();
		double h = sqrt(SQ(c.r) - SQ(d));
		Point v = x.sub(c.p);
		return makeVec(c.p.add(v.scale(d)).add(v.scale(h)), c.p.add(v.scale(d)).add(v.scale(-h)));
	}
	static ArrayList<Point> circcirc(Circle a, Circle b){
		double d = a.p.dist(b.p);
		if(d > a.r + b.r + eps) return new ArrayList<Point>();
		if(d < abs(a.r - b.r) - eps) return new ArrayList<Point>();
		double x = (SQ(d) - SQ(b.r) + SQ(a.r)) / 2*d;
		double y = sqrt(SQ(a.r) - SQ(x));
		Point v = b.p.sub(a.p);
		return makeVec(a.p.add(v.scale(x)).add(v.perp().scale(y)), a.p.add(v.scale(x)).add(v.perp().scale(-y)));
	}
	static ArrayList<Line> circcirctan(Circle a, Circle b){//tested
		if(a.r < b.r)
			return circcirctan(b, a);
		ArrayList<Line> res = new ArrayList<Line>();
		double d = a.p.dist(b.p);
		double d1 = a.r*d/(a.r + b.r);
		double t = acos(a.r/d1);
		Point v = b.p.sub(a.p);
		res.add(new Line(a.p.add(v.scale(a.r).rot(t)), b.p.add(v.scale(-b.r).rot(t))));
		res.add(new Line(a.p.add(v.scale(a.r).rot(-t)), b.p.add(v.scale(-b.r).rot(-t))));
		t = asin((a.r-b.r)/d)+PI/2;
		v = a.p.sub(b.p);
		res.add(new Line(a.p.add(v.scale(a.r).rot(t)), b.p.add(v.scale(b.r).rot(t))));
		res.add(new Line(a.p.add(v.scale(a.r).rot(-t)), b.p.add(v.scale(b.r).rot(-t))));
		return res;
	}

	//3d
	static class Point3{
		double x, y, z;
		Point3(double x, double y, double z) {  this.x = x; this.y = y; this.z = z; }
		static Point3 sphere(double theta, double phi, double r){
			return new Point3(r*cos(theta)*sin(phi),r*sin(theta)*sin(phi),r*cos(theta));
		}
		double[] ang(){ return new double[]{atan(y/x), acos(z/len())}; }
		Point proj(){ return new Point(x, y); }
		Point3 add(Point3 p){ return new Point3(x+p.x, y+p.y, z+p.z); }
		Point3 sub(Point3 p){ return new Point3(x-p.x, y-p.y, z-p.z); }
		double dot(Point3 p){ return x*p.x+ y*p.y+ z*p.z; }
		Point3 cross(Point3 p){ return new Point3(y*p.z-p.y*z, z*p.x-p.z*x, x*p.y-p.x*y); }
		Point3 mult(double d){ return new Point3(x*d, y*d, z*d); }
		double len(){ return sqrt(x*x+y*y+z*z); }
		Point3 scale(double d){ return mult(d/len()); }
		double dist(Point3 p){ return sub(p).len(); }
		boolean equals(Point3 p){ return EQ(dist(p), 0); }
	}
	static Point3[] getbasis(Point3 z){
		z = z.scale(1);
		Point3 t = new Point3(1, 0, 0);
		Point3 y = z.cross(t);
		if(EQ(y.len(), 0)){
			t = new Point3(0, 1, 0);
			y = z.cross(t);
		}
		Point3 x = y.cross(z);
		assert(x.cross(y).equals(z));
		return new Point3[]{x, y, z};
	}
	static Point3 trans(Point3[] B, Point3 p){
		return new Point3(B[0].dot(p), B[1].dot(p), B[2].dot(p));
	}
	static Point3 invtrans(Point3[] B, Point3 p){
		return B[0].mult(p.x).add(B[1].mult(p.y)).add(B[2].mult(p.z));
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.HashMap;

public class C62 {

    static StreamTokenizer in;
    static PrintWriter out;

    static int nextInt() throws IOException {
        in.nextToken();
        return (int)in.nval;
    }

    static String nextString() throws IOException {
        in.nextToken();
        return in.sval;
    }

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

        int n = nextInt();
        l = new int[n][n];
        h = new int[n][n];
        a = new int[n][n];
        for (int i = 0; i < n*(n-1)/2; i++) {
            int f = nextInt()-1, t = nextInt()-1;
            l[f][t] = nextInt();
            h[f][t] = nextInt();
            a[f][t] = nextInt();
        }

        int min = 0, max = Integer.MAX_VALUE;
        for (int i = 0; i < n-1; i++)
            for (int j = 0; j < n; j++) {
                int L = 0, H = 0;
                for (int k = 0; k <= i; k++)
                    for (int m = i+1; m < n; m++) {
                        L += l[k][m];
                        H += h[k][m];
                    }
                min = Math.max(min, L);
                max = Math.min(max, H);
            }

        e = new int[n*(n-1)/2][];
        for (int i = 0, k = 0; i < n-1; i++)
            for (int j = i+1; j < n; j++, k++)
                e[k] = new int[]{i, j};
        p = new int[n-1];
        p[0] = min;
        s = min;
        int ans = solve(0);
        out.println(ans == Integer.MIN_VALUE ? "-1 -1" : min + " " + solve(0));

        out.flush();
    }

    static int[][] l, h, a;
    static int[][] e;
    static int[] p;
    static int s;

    static HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();

    static int solve(int x) {
        if (x >= e.length)
            return s == 0 ? 0 : Integer.MIN_VALUE;
        int key = getKey(x);
        if (map.containsKey(key)) return map.get(key);
        int f = e[x][0], t = e[x][1];
        if (f > 1 && p[f-1] > 0) {
            map.put(key, Integer.MIN_VALUE);
            return Integer.MIN_VALUE;
        }
        int res = Integer.MIN_VALUE;
        for (int i = l[f][t]; i <= h[f][t]; i++) {
            if (i > p[f]) break;
            p[f] -= i;
            if (t < p.length) p[t] += i;
            else s -= i;
            int cur = solve(x+1);
            if (cur != Integer.MIN_VALUE)
                res = Math.max(res, cur + (i > 0 ? a[f][t] + i*i : 0));
            if (t < p.length) p[t] -= i;
            else s += i;
            p[f] += i;
        }
        map.put(key, res);
        return res;
    }

    static int getKey(int x) {
        int res = x;
        for (int i = 0; i < p.length; i++)
            res = res*26 + p[i];
        return res;
    }
}


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

public class solver implements Runnable{

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

 int[][] dp;
 int mod 1000000007

 public void solver() throws IOException{

  String s=nextToken();
  String w=nextToken();
  int n=s.length();
  int m=w.length();

  dp=new int[5005][5005];

  dp[0][0]=0;
  //for(int j=0;j<=m;j++) dp[0][j]=1;
  //for(int i=0;i<=n;i++) dp[i][0]=1;

  for(int i=1;i<=n;i++)
  for(int j=1;j<=m;j++)
  {
   dp[i][j]=dp[i][j-1];
   if(s.charAt(i-1)==w.charAt(j-1))
    dp[i][j]+=1+dp[i-1][j-1];

   dp[i][j]%=mod;
  }

  int ans=0;

  for(int i=0;i<=n;i++)
  {
   ans+=dp[i][m];
   ans%=mod;
  }

  out.print(ans);

  /*System.out.println(dp[n][m]);

  for(int i=0;i<10;i++){
  System.out.print(i+":");
  for(int j=0;j<10;j++)
   System.out.print(dp[i][j]+" ");
  System.out.println();
  }*/

 }

 public void run(){
  try{
    reader=new BufferedReader(new InputStreamReader(System.in));
    //reader=new BufferedReader(new FileReader("input.txt"));
    tokenizer=null;
    out=new PrintWriter(System.out);
	 solver();
    out.close();
    reader.close();
  }
  catch(Exception e){
   e.printStackTrace();
   System.exit(1);
  }

 }

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

 BufferedReader reader;
 StringTokenizer tokenizer;
 PrintWriter out;

}


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

public class E {

	BufferedReader br;
	PrintWriter out;
	StringTokenizer st;
	boolean eof;

	void solve() throws IOException {
		int n = nextInt();
		int m = nextInt();

		long[] a = new long[n];
		for (int i = 0; i < n; i++)
			a[i] = nextLong();

		long ans = 0;

		int maxP = m / n;
		for (int p = 1; p <= maxP; p++) {
			long minLastSum = (long)p * (p + 1) / 2 * n;
			if (a[n - 1] < minLastSum)
				continue;
			long maxLastSum = (long)m * p - (long)n * p * (p - 1) / 2;
			long[] money = new long[n];
			money[n - 1] = Math.min(maxLastSum, a[n - 1]);
			for (int i = n - 2; i >= 0; i--)
				money[i] = Math.min(a[i], money[i + 1] - p);

			long firstMax = (long)(m + 1) * p - (long)n * p * (p + 1) / 2;
			long diff = firstMax - money[0];
			if (diff < 0)
				throw new AssertionError();
			long firstPay = diff <= m - p * n ? (m - p * n + 1 - diff) : 1;
			long free = (m - firstPay + 1) - n * p;

			long cur = money[0];
			long last = money[0];
			for (int j = 1; j < n; j++) {
				long now = last + p;
				long shift = Math.min(free, money[j] - now);
				free -= shift;
				last = now + shift;
				cur += last;
			}

			ans = Math.max(ans, cur);
		}

		out.println(ans);
	}

	void inp() throws IOException {
		br = new BufferedReader(new InputStreamReader(System.in));
		out = new PrintWriter(System.out);
		solve();
		out.close();
	}

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

	String nextToken() {
		while (st == null || !st.hasMoreTokens()) {
			try {
				st = new StringTokenizer(br.readLine());
			} catch (Exception e) {
				eof = true;
				return null;
			}
		}
		return st.nextToken();
	}

	String nextString() {
		try {
			return br.readLine();
		} catch (IOException e) {
			eof = true;
			return null;
		}
	}

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

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

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


import static java.lang.Math.abs;
import static java.lang.Math.max;

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

public class E {

	private void solve() throws IOException {
		int[] abc = new int[3];
		for (int i = 0; i < 3; i++) {
			abc[i] = nextInt();
			moveDistance[i] = nextInt();
			throwDistance[i] = nextInt();
		}
		Position init = new Position(abc[0], abc[1], abc[2], 511, 0);
		queue.add(init);
		visited.add(init);
		best = Integer.MIN_VALUE;
		// long time = System.currentTimeMillis();
		bfs();
		// System.err.println(visited.size());
		// System.err.println(System.currentTimeMillis() - time);
		out.println(best);
	}

	static Queue<Position> queue = new ArrayDeque<E.Position>();
	static HashSet<Position> visited = new HashSet<E.Position>();
	static Position temp = new Position(0, 0, 0, 0, 0);
	static int[] moveDistance = new int[3];
	static int[] throwDistance = new int[3];
	static int best;

	static int[] array = new int[3];

	static boolean containedInArray(int i) {
		for (int j = 0; j < 3; j++) {
			if (array[j] == i) {
				return true;
			}
		}
		return false;
	}

	static void bfs() {
		while (!queue.isEmpty()) {
			Position p = queue.poll();
			p.copyTo(temp);
			for (int i = 0; i < 3; i++) {
				array[i] = p.getPos(i);
				best = max(best, array[i]);
			}

			for (int manMoving = 0; manMoving < 3; manMoving++) {
				int pos = temp.getPos(manMoving);
				int holding = ((temp.holding123 >> 2 * manMoving) & 3) - 1;
				if (beingHeld(temp.holding123, manMoving)) {
					continue;
				}

				if (holding == -1 && bit(temp.movesMask, (3 * manMoving))) {
					temp.movesMask ^= 1 << 3 * manMoving;
					for (int i = max(pos - moveDistance[manMoving], 1); i <= pos
							+ moveDistance[manMoving]; i++) {
						if (containedInArray(i)) {
							continue;
						}
						temp.setPosition(manMoving, i);
						if (!visited.contains(temp)) {
							Position t = temp.copy();
							visited.add(t);
							queue.add(t);
						}
					}
					temp.setPosition(manMoving, pos);
					temp.movesMask ^= 1 << 3 * manMoving;
				}

				if (holding != -1 && bit(temp.movesMask, 3 * manMoving + 1)) {
					temp.movesMask ^= 1 << 3 * manMoving + 1;
					temp.holding123 ^= (holding + 1) << 2 * manMoving;
					int otherManHolds = ((temp.holding123 >> 2 * holding) & 3) - 1;
					for (int i = max(pos - throwDistance[manMoving], 1); i <= pos
							+ throwDistance[manMoving]; i++) {
						if (containedInArray(i)) {
							continue;
						}
						temp.setPosition(holding, i);
						if (otherManHolds != -1) {
							temp.setPosition(otherManHolds, i);
						}
						if (!visited.contains(temp)) {
							Position t = temp.copy();
							visited.add(t);
							queue.add(t);
						}
					}
					if (otherManHolds != -1) {
						temp.setPosition(otherManHolds, pos);
					}
					temp.holding123 ^= (holding + 1) << 2 * manMoving;
					temp.setPosition(holding, pos);
					temp.movesMask ^= 1 << 3 * manMoving + 1;
				}

				if (bit(temp.movesMask, 3 * manMoving + 2)) {
					temp.movesMask ^= 1 << 3 * manMoving + 2;
					for (int i = 0; i < 3; i++) {
						if (i == manMoving) {
							continue;
						}
						int oldpos = temp.getPos(i);
						if (abs(oldpos - pos) != 1) {
							continue;
						}
						if (beingHeld(temp.holding123, i)) {
							continue;
						}
						temp.holding123 ^= (i + 1) << (2 * manMoving);
						temp.setPosition(i, pos);
						if (!visited.contains(temp)) {
							Position t = temp.copy();
							visited.add(t);
							queue.add(t);
						}
						temp.holding123 ^= (i + 1) << (2 * manMoving);
						temp.setPosition(i, oldpos);
					}
					temp.movesMask ^= 1 << 3 * manMoving + 2;
				}
			}
		}
	}

	static boolean beingHeld(int holding, int man) {
		++man;
		if (man == (holding & 3))
			return true;
		if (man == ((holding >> 2) & 3))
			return true;
		if (man == ((holding >> 4) & 3))
			return true;
		return false;
	}

	static boolean bit(int mask, int bit) {
		return (mask & (1 << bit)) != 0;
	}

	static class Position {
		int a, b, c;
		int movesMask;
		int holding123;

		void setPosition(int man, int pos) {
			if (man == 0) {
				a = pos;
			} else {
				if (man == 1) {
					b = pos;
				} else {
					c = pos;
				}
			}
		}

		int getPos(int manMoving) {
			return manMoving == 0 ? a : manMoving == 1 ? b : c;
		}

		Position() {
		}

		Position copy() {
			Position res = new Position();
			copyTo(res);
			return res;
		}

		public Position(int a, int b, int c, int movesMask, int holding123) {
			this.a = a;
			this.b = b;
			this.c = c;
			this.movesMask = movesMask;
			this.holding123 = holding123;
		}

		void copyTo(Position to) {
			to.a = a;
			to.b = b;
			to.c = c;
			to.movesMask = movesMask;
			to.holding123 = holding123;
		}

		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + a;
			result = prime * result + b;
			result = prime * result + c;
			result = prime * result + holding123;
			result = prime * result + movesMask;
			return result;
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			Position other = (Position) obj;
			if (a != other.a)
				return false;
			if (b != other.b)
				return false;
			if (c != other.c)
				return false;
			if (holding123 != other.holding123)
				return false;
			if (movesMask != other.movesMask)
				return false;
			return true;
		}
	}

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

	static BufferedReader br;
	static StringTokenizer st;
	static PrintWriter out;

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

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

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

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


import java.io.BufferedInputStream;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.Locale;
import java.util.Scanner;

public class TaskD {
    private static final String QUICK_ANSWER = "NO";
    private final Scanner in;
    private final StringBuilder out;
    private final int n;
    private final char[] chars;
    private final boolean[] up;
    int minPos;

    public TaskD(Scanner in, StringBuilder out) throws QuickAnswer {
        this.in = in;
        this.out = out;
        n = nextInt();
        chars = nextString().toCharArray();
        int lev = 0;
        int minLev = 0;
        int minPos = 0;
        for (int i = 0; i < n; i++) {
            if (chars[i] == '(') ++lev;
            else --lev;
            if (lev < minLev) {
                minLev = lev;
                minPos = i + 1;
            }
        }
        if (lev != 0) {
            quickAnswer("0\n1 1");
        }
        minPos %= n;
        this.minPos = minPos;
        up = new boolean[n];
        for (int i = 0; i < n; i++) {
            up[i] = chars[(i + minPos) % n] == '(';
        }
    }

    public void solve() throws QuickAnswer {
        int lev = 0;
        int i1 = 0;
        int i2 = 0;
        int bonus = 0;
        int istart = -1;
        int b = 1;
        for (int i = 0; i < n; i++) {
            if (up[i]) lev++;
            else lev--;
            if (lev == 2) {
                if (up[i]) istart = i;
                else ++b;
            } else if (lev == 1 && !up[i]) {
                if (b > bonus) {
                    i1 = istart;
                    i2 = i;
                    bonus = b;
                }
                istart = -1;
                b = 1;
            }
        }

        up[i1] = false;
        up[i2] = true;
        lev = 0;
        int cnt = 0;
        for (int i = 0; i < n; i++) {
            if (up[i]) lev++;
            else lev--;
            if (lev == 0) ++cnt;
        }
        up[i1] = true;
        up[i2] = false;

        int cnt1 = 0;
        int last0 = 0;
        for (int i = 0; i < n; i++) {
            if (up[i]) lev++;
            else lev--;
            if (lev == 1) ++cnt1;
            if (lev == 0) {
                if (cnt1 > cnt) {
                    i1 = last0;
                    i2 = i;
                    cnt = cnt1;
                }
                cnt1 = 0;
                last0 = i + 1;
            }
        }

        println(cnt);
        print(1 + (i1 + minPos) % n, 1 + (i2 + minPos) % n);

    }

    // Common functions

    void quickAnswer(String answer) throws QuickAnswer {
        throw new QuickAnswer(answer);
    }

    void quickAnswer() throws QuickAnswer {
        quickAnswer(QUICK_ANSWER);
    }

    static class QuickAnswer extends Exception {
        private String answer;

        public QuickAnswer(String answer) {
            this.answer = answer;
        }
    }

    void print(Object... args) {
        String prefix = "";
        for (Object arg : args) {
            out.append(prefix);
            out.append(arg);
            prefix = " ";
        }
    }

    void println(Object... args) {
        print(args);
        out.append("\n");
    }

    void printsp(Object... args) {
        print(args);
        out.append(" ");
    }

    int nextInt() {
        return in.nextInt();
    }

    long nextLong() {
        return in.nextLong();
    }

    String nextString() {
        String res = in.nextLine();
        return res.trim().isEmpty() ? in.nextLine() : res;
    }

    int[] nextInts(int count) {
        int[] res = new int[count];
        for (int i = 0; i < count; ++i) {
            res[i] = in.nextInt();
        }
        return res;
    }

    long[] nextLongs(int count) {
        long[] res = new long[count];
        for (int i = 0; i < count; ++i) {
            res[i] = in.nextInt();
        }
        return res;
    }

    public static void main(String[] args) {
        doMain(System.in, System.out);
    }

    static void doMain(InputStream inStream, PrintStream outStream) {
        Scanner in = new Scanner(new BufferedInputStream(inStream)).useLocale(Locale.ENGLISH);
        StringBuilder totalOut = new StringBuilder();
        int count = 1;
        //count = in.nextInt();
        while (count-- > 0) {
            try {
                StringBuilder out = new StringBuilder();
                new TaskD(in, out).solve();
                totalOut.append(out.toString());
            } catch (QuickAnswer e) {
                totalOut.append(e.answer);
            }
            if (count > 0) {
                totalOut.append("\n");
            }
        }
        outStream.print(totalOut.toString());
    }
}


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

/* Name of the class has to be "Main" only if the class is public. */
public class Main
{
	public static void main (String[] args) throws java.lang.Exception
	{
		// your code goes here
		Scanner scanner = new Scanner(System.in);
		int a = scanner.nextInt();
		int h = scanner.nextInt();
		int w = scanner.nextInt();
		int g = h+a, gn = w+a;
		while (gn>0) {
			int t = gn;
			gn = g%gn;
			g = t;

		}

		int k = g/a;

		if (k>0&&1.0*g/k<=h&&1.0*g/k<=w) {
			System.out.println(1.0*g/k-a);
		} else {
			System.out.println(-1);
		}

	}
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.io.BufferedWriter;
import java.util.HashMap;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
import java.util.Map;
import java.util.Map.Entry;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.BufferedReader;
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);
        TaskG solver = new TaskG();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskG {
        public long[] prime;
        public long[] power;
        public int mod = 1000000007;
        public long[] dp;
        public int nzeros;

        public void solve(int testNumber, InputReader in, OutputWriter out) {
            char[] c = in.next().toCharArray();
            nzeros = 0;
            for (int i = 0; i < c.length; i++) {
                if (c[i] == '0') {
                    nzeros++;
                }
            }
            int n = in.nextInt();
            long mult = 1;
            prime = new long[n];
            power = new long[n];
            for (int i = 0; i < n; i++) {
                prime[i] = in.nextInt();
                power[i] = in.nextInt();
                mult = mult * Utils.mod_exp(prime[i], power[i] - 1, mod) % mod;
            }
            Arrays.sort(prime);
            int k = 0;
            while (k < n && prime[k] <= c.length) k++;
            dp = new long[nzeros + 1];
            dp[0] = 1;
            for (int i = k; i < n; i++) {
                long[] next = new long[dp.length];
                for (int j = 0; j < dp.length; j++) {
                    // skip all
                    next[j] = (next[j] + (prime[i] - c.length) * dp[j]) % mod;
                    // hit exist
                    next[j] = (next[j] + (nzeros - j) * dp[j]) % mod;
                    // hit new
                    if (j > 0) {
                        next[j] = (next[j] + j * dp[j - 1]) % mod;
                    }
                }
                dp = next;
            }
            HashMap<Long, Integer> dp2 = new HashMap<>();
            dp2.put(0L, 1);
            for (int i = 0; i < k; i++) {
                HashMap<Long, Integer> next = new HashMap<>();
                for (int j = 0; j < prime[i]; j++) {
                    boolean bad = false;
                    long d = 0;
                    for (int w = j; w < c.length; w += prime[i]) {
                        d |= 1L << w;
                        if (c[w] == '1') {
                            bad = true;
                        }
                    }
                    if (!bad) {
                        dp2.forEach((k,v) -> {
                            long nk = k | d;
                            next.put(nk, (v+next.getOrDefault(nk, 0)) % mod);
                        });
                    }
                }
                dp2 = next;
            }
            long nways = 0;
            dp2.forEach((k,v) -> nways = (nways + dp[nzeros - Long.bitCount(k)] * v) % mod);
            nways = nways * mult % mod;
            out.println(nways);
        }

    }

    static class OutputWriter {
        private final PrintWriter writer;

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

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

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

        public void println(long i) {
            writer.println(i);
        }

    }

    static class Utils {
        public static long mod_exp(long b, long e, long mod) {
            long res = 1;
            while (e > 0) {
                if ((e & 1) == 1)
                    res = (res * b) % mod;
                b = (b * b) % mod;
                e >>= 1;
            }
            return res;
        }

    }

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

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

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

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

    }
}