import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UncheckedIOException;
import java.nio.charset.Charset;
import java.util.StringTokenizer;
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
 *
 * @author mikit
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        LightScanner in = new LightScanner(inputStream);
        LightWriter out = new LightWriter(outputStream);
        CMisterBAndBoringGame solver = new CMisterBAndBoringGame();
        solver.solve(1, in, out);
        out.close();
    }

    static class CMisterBAndBoringGame {
        public void solve(int testNumber, LightScanner in, LightWriter out) {
            // out.setBoolLabel(LightWriter.BoolLabel.YES_NO_FIRST_UP);
            int a = in.ints(), b = in.ints(), l = in.ints() - 1, r = in.ints() - 1;

            int min = 26;
            for (char p = 'a'; p <= 'z'; p++) {
                for (char q = (char) ('a' + a); q <= 'z'; q++) {
                    StringBuilder rep = new StringBuilder();
                    for (int i = 0; i < a; i++) rep.append((char) (i + 'a'));
                    for (int i = 0; i < b; i++) rep.append(p);
                    outer:
                    for (int i = 0; i < a; i++) {
                        boolean[] f = new boolean[26];
                        for (int j = b; j < a + b + i; j++) {
                            f[rep.charAt(j) - 'a'] = true;
                        }
                        for (int j = 0; j < 26; j++) {
                            if (!f[j]) {
                                rep.append((char) (j + 'a'));
                                continue outer;
                            }
                        }
                    }
                    for (int i = 0; i < b; i++) rep.append(q);

                    boolean[] flag = new boolean[26];
                    if (r - l + 1 >= 100_000) {
                        for (int i = 0; i < rep.length(); i++) {
                            flag[rep.charAt(i) - 'a'] = true;
                        }
                    } else {
                        for (int i = l; i <= r; i++) {
                            flag[rep.charAt(i % rep.length()) - 'a'] = true;
                        }
                    }

                    //System.out.println(rep);

                    int ans = 0;
                    for (int i = 0; i < 26; i++) if (flag[i]) ans++;
                    min = Math.min(ans, min);
                }
            }
            out.ans(min).ln();
        }

    }

    static class LightScanner {
        private BufferedReader reader = null;
        private StringTokenizer tokenizer = null;

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

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

        public int ints() {
            return Integer.parseInt(string());
        }

    }

    static class LightWriter implements AutoCloseable {
        private final Writer out;
        private boolean autoflush = false;
        private boolean breaked = true;

        public LightWriter(Writer out) {
            this.out = out;
        }

        public LightWriter(OutputStream out) {
            this(new BufferedWriter(new OutputStreamWriter(out, Charset.defaultCharset())));
        }

        public LightWriter print(char c) {
            try {
                out.write(c);
                breaked = false;
            } catch (IOException ex) {
                throw new UncheckedIOException(ex);
            }
            return this;
        }

        public LightWriter print(String s) {
            try {
                out.write(s, 0, s.length());
                breaked = false;
            } catch (IOException ex) {
                throw new UncheckedIOException(ex);
            }
            return this;
        }

        public LightWriter ans(String s) {
            if (!breaked) {
                print(' ');
            }
            return print(s);
        }

        public LightWriter ans(int i) {
            return ans(Integer.toString(i));
        }

        public LightWriter ln() {
            print(System.lineSeparator());
            breaked = true;
            if (autoflush) {
                try {
                    out.flush();
                } catch (IOException ex) {
                    throw new UncheckedIOException(ex);
                }
            }
            return this;
        }

        public void close() {
            try {
                out.close();
            } catch (IOException ex) {
                throw new UncheckedIOException(ex);
            }
        }

    }
}


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

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

    static class TaskC {
        public void solve(int testNumber, FastReader in, PrintWriter out) {
            int a = in.nextInt();
            int b = in.nextInt();
            int l = in.nextInt() - 1;
            int r = in.nextInt() - 1;
            int ab = a + b;
            int m = 4;
            int[] cc = new int[ab * m];
            int h = l / ab;
            l -= h * ab;
            r -= h * ab;
            h = (r - l + 1) / ab;
            if (h > 2)
                r -= (h - 2) * ab;
            int d = a > b ? a - b : 1;
            for (h = 0; h < m; h++) {
                for (int k = 0; k < a - d; k++)
                    cc[(a + b) * h + k] = k;
                for (int k = 0; k < d; k++)
                    cc[(a + b) * h + a - d + k] = h % 2 == 0 ? a - d + k : a + k;
            }
            int min = a + a;
            for (int k0 = 1; k0 <= d; k0++) {
                for (int k = 0; k < b; k++)
                    cc[(a + b) * 0 + a + k] = cc[(a + b) * 0 + a - k0];
                for (int k1 = 1; k1 <= d; k1++) {
                    for (int k = 0; k < b; k++)
                        cc[(a + b) * 1 + a + k] = cc[(a + b) * 1 + a - k1];
                    for (int k2 = 1; k2 <= d; k2++) {
                        for (int k = 0; k < b; k++)
                            cc[(a + b) * 2 + a + k] = cc[(a + b) * 2 + a - k2];
                        for (int k3 = 1; k3 <= d; k3++) {
                            for (int k = 0; k < b; k++)
                                cc[(a + b) * 3 + a + k] = cc[(a + b) * 3 + a - k3];
                            min = Math.min(min, count(cc, l, r));
                        }
                    }
                }
            }
            out.println(min);
        }

        static int count(int[] cc, int l, int r) {
            boolean[] used = new boolean[24];
            int cnt = 0;
            for (int i = l; i <= r; i++) {
                int c = cc[i];
                if (!used[c]) {
                    used[c] = true;
                    cnt++;
                }
            }
            return cnt;
        }

    }

    static class FastReader {
        private InputStream stream;
        private byte[] buf = new byte[8192];
        private int curChar;
        private int pnumChars;
        private FastReader.SpaceCharFilter filter;

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

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

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

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

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

        public interface SpaceCharFilter {
            public boolean isSpaceChar(int ch);

        }

    }
}


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

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

    static class TaskC {
        public void solve(int testNumber, InputReader in, PrintWriter out) {
            int a = in.nextInt();
            int b = in.nextInt();
            int l = in.nextInt();
            int r = in.nextInt();

            out.println(fun(a, b, l, r));
        }

        static int fun(int a, int b, int l, int r) {
            if ((r - l + 1) > 2 * (a + b))
                if (a <= b)
                    return a + 1;
                else
                    return (2 * a - b);

            int[] flag = new int[3 * (a + b) + 1];

            int temp = 0;
            for (int i = 1; i <= a; i++) {
                flag[i] = i;
                temp = i;
            }

            for (int i = a + 1; i <= a + b; i++) {
                flag[i] = temp;
            }

            for (int i = a + b + 1; i <= a + b + a; i++) {
                int tc = 1;
                while (in(flag, tc, a + b - a + 1, i - 1))
                    tc++;
                flag[i] = tc;
                temp = flag[i];
            }
            for (int i = a + b + a + 1; i <= a + b + a + b; i++) {
                flag[i] = temp;
            }
            for (int i = 2 * (a + b) + 1; i <= 3 * (a + b); i++) {
                flag[i] = flag[i - (a + b)];
            }

            int[] flagc = new int[25];
            int templ = l % (a + b);
            if (templ == 0) templ += a + b;
            int tempr = r - l + templ;
            if (tempr < templ) tempr += a + b;
            for (int i = templ; i <= tempr; i++) {
                flagc[flag[i]] = 1;
            }

            int res = 0;
            for (int i = 1; i <= 24; i++)
                res += flagc[i];

            return res;

        }

        static boolean in(int[] a, int b, int l, int r) {
            for (int i = l; i <= r; i++) {
                if (a[i] == b)
                    return true;
            }
            return false;
        }

    }

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

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

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

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

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

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

        public interface SpaceCharFilter {
            public boolean isSpaceChar(int ch);

        }

    }
}


/*
javac f.java && java f
*/

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

public class f {
	public static void main(String[] args) { new f(); }
	FS in = new FS();
	PrintWriter out = new PrintWriter(System.out);

	int n;
	long[] a;

	int MAX = 5001;
	int pcnt, pr[];
	int[][] vp, cs;
	boolean[] isnt;

	f() {
		pcnt = 0;
		isnt = new boolean[MAX];
		isnt[0] = true; isnt[1] = true;
		for (int i = 2; i < MAX; i++)
			if (!isnt[i]) {
				pcnt++;
				for (int j = (i << 1); j < MAX; j += i)
					isnt[j] = true;
			}
		pr = new int[pcnt]; pcnt = 0;
		for (int i = 0; i < MAX; i++)
			if (!isnt[i])
				pr[pcnt++] = i;

		/*
		long ops = 0, gap3 = 0;
		for (int i = 0; i < pcnt; i++) {
			long del = i == 0 ? 1 : pr[i] - pr[i - 1];
			out.printf("del = %d | p = %d%n", del, pr[i]);
			ops += (del * del * del);
			gap3 = max(gap3, del * del * del);
		}
		out.println("--> " + ops + " OW3 " + gap3);
		*/

		vp = new int[MAX][pcnt];
		for (int i = 2; i < MAX; i++)
			for (int j = 0; j < pcnt; j++) {
				int k = i;
				while (k > 0) {
					vp[i][j] += (k / pr[j]);
					k /= pr[j];
				}
			}
		cs = new int[MAX][pcnt + 1];
		for (int i = 2; i < MAX; i++)
			for (int j = 1; j <= pcnt; j++)
				cs[i][j] = vp[i][j - 1] + cs[i][j - 1];

		n = in.nextInt();
		a = new long[MAX];
		for (int i = 0; i < n; i++) {
			int x = in.nextInt();
			if (x == 0) x++;
			a[x]++;
		}
		long[] f = new long[MAX + 1];
		for (int i = 1; i <= MAX; i++)
			f[i] = f[i - 1] + a[i - 1];

		long[] dist = new long[MAX + 1];
		for (int i = 1; i <= MAX; i++)
			dist[i] = dist[i - 1] + a[i - 1] * cs[i - 1][pcnt];

		// F I X  T H I S
		long ans = dist[MAX];
		int l = 2, r;
		for (int i = 0; i < pcnt; i++) {
			r = i == pcnt - 1 ? MAX - 1 : pr[i + 1] - 1;
			// everybody outside this range of highest prime must travel to 1 first
			// then travel up to the lca we're trying at each step
			long blw = dist[MAX] - (dist[r + 1] - dist[l]);
			// so when trying lca(j, k) we need to know how many primes are on in it
			// and how far every person in the range [l, r] will need to travel
			for (int x = r; x >= l; x--)
				for (int y = x; y >= l; y--) {
					// lca will be gotten as (pIDX, cnt)
					int[] lca = {-1, 0};
					for (int z = i; z >= 0; z--)
						if (vp[x][z] != vp[y][z]) {
							lca[0] = z;
							lca[1] = min(vp[x][z], vp[y][z]);
							break;
						}

					long up = lca[1] + cs[x][pcnt] - cs[x][lca[0] + 1];
					up *= (f[MAX] - f[r + 1] + f[l]);

					long abv = 0;
					for (int z = r; z >= l; z--) {
						if (x == z && y == z) continue;
						// given lca(x, y) = {w, cnt}
						// if we get to w add in prefix of other primes in a[z] * cs[w - 1]
						// add a[z] * [abs(cnt - cnt[z]) to abv
						// if we dont get to w before they differ
						// add a[z] * (diff to here + here up)
						for (int w = i; w >= lca[0]; w--) {
							if (w == lca[0]) {
								abv += a[z] * cs[z][w];
								abv += a[z] * abs(vp[z][w] - lca[1]);
								break;
							}
							if (vp[z][w] != vp[x][w]) {
								abv += a[z] * cs[z][w];
								abv += a[z] * abs(vp[z][w] - vp[x][w]);
								abv += a[z] * (cs[x][w] - cs[x][lca[0] + 1]);
								abv += a[z] * lca[1];
								break;
							}
						}
					}
					ans = min(ans, abv + blw + up);
				}
			l = r + 1;
		}

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

	int abs(int x) { if (x < 0) return -x; return x; }
	long abs(long x) { if (x < 0) return -x; return x; }
	int max(int x, int y) { if (x < y) return y; return x; }
	int min(int x, int y) { if (x > y) return y; return x; }
	long max(long x, long y) { if (x < y) return y; return x; }
	long min(long x, long y) { if (x > y) return y; return x; }
	int gcd(int x, int y) { while (y != 0) { x = y^(x^(y = x)); y %= x; } return x; }
	long gcd(long x, long y) { while (y != 0) { x = y^(x^(y = x)); y %= x; } return x; }
	long lcm(int x, int y) { long xy = x; xy *= y; return xy / gcd(x, y); }
	long lcm(long x, long y) { return (x * y) / gcd(x, y); }

	class FS {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer("");
		String next() {
			while (!st.hasMoreTokens()) {
				try { st = new StringTokenizer(br.readLine()); }
				catch (Exception e) {}
			} return st.nextToken();
		}
		int nextInt() { return Integer.parseInt(next()); }
		long nextLong() { return Long.parseLong(next()); }
		double nextDouble() { return Double.parseDouble(next()); }

		void intArr(int sz, int[] x) { for (int i = 0; i < sz; i++) x[i] = nextInt(); }
		void longArr(int sz, long[] x) { for (int i = 0; i < sz; i++) x[i] = nextLong(); }
		void doubleArr(int sz, double[] x) { for (int i = 0; i < sz; i++) x[i] = nextDouble(); }
	}
}


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

public class f {
   public static FS sc;
   public static PrintWriter out;
   public static ArrayList<Integer>[] adj;
   public static int n;

   public static HashMap<Long, Long> memo, memoSize;

   public static void main(String[] Args) throws Exception {
      sc = new FS(System.in);
      out=new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
      int n = sc.nextInt();
      int MAX =5010;
      int[][] dist = new int[MAX][MAX];

      BIT bi = new BIT(MAX);
      int[] primes = new int[MAX];
      int[] factDivs = new int[MAX];
      int[] valDivs = new int[MAX];
      Arrays.fill(primes, 1);
      for (int i = 2; i < MAX; i++){
         if (primes[i] == 1){
            for (int j = i  * 2; j < MAX; j+=i)
               primes[j] = i;
            valDivs[i]=1;
            primes[i] = i;
         }else
            valDivs[i]=valDivs[i/primes[i]] + 1;
         factDivs[i] = factDivs[i-1] + valDivs[i];

      }/*
      for (int i = 0; i<10; i++)
      {
         System.out.println(primes[i] +" " +valDivs[i] +" " +factDivs[i]);
      }*/

      for (int i = 2; i < MAX; i++){
         int last = bi.sum(MAX-1) - bi.sum(primes[i]-1);
         int j = i - 1;
         dist[i][i] = factDivs[i];
         while (last != 0) {
            dist[i][j] = dist[j][i] = last;
            int last2 = dist[i-1][j-1];
            if (last > last2)
               last = last2;
            j--;
         }
         int ii = i;
         while (ii != 1) {
            bi.inc(primes[ii],1);
            ii /= primes[ii];
         }
      }/*
      for (int i = 1; i < 6; i++){
         for (int j = 1; j < 6;j++) {
            int actDist = factDivs[i] + factDivs[j] - dist[i][j]*2;
            System.out.print(actDist +" " );
         }
         System.out.println();
      }*/

      long[] count = new long[MAX];
      for (int i = 0; i<n; i++){
         int x = sc.nextInt();
         if (x == 0)
            x++;
         count[x]++;
      }
      long ans = Long.MAX_VALUE;
      for (int i = 1; i< MAX; i++){
         long tans = 0;
         for (int j = 1; j< MAX; j++){
            tans += count[j] * (factDivs[i] + factDivs[j] - dist[i][j]*2);
         }
         if(tans < ans)
            ans = tans;
      }
      out.println(ans);
      out.close();
   }
   public static class BIT {
      int n;
      int[] v;
      BIT(int N) { v = new int[n=N]; }
      int sum(int x) { return x<0?0:(v[x]+sum((x&(x+1))-1)); }
      void inc(int p, int x) { for(int i=p; i<n; i|=(i+1)) v[i]+=x; }
   }

   public static class FS {
      BufferedReader br;
      StringTokenizer st;
      FS(InputStream in) throws Exception {
         br = new BufferedReader(new InputStreamReader(in));
         st = new StringTokenizer(br.readLine());
      }
      String next() throws Exception {
         if(st.hasMoreTokens())
            return st.nextToken();
         st = new StringTokenizer(br.readLine());
         return next();
      }
      int nextInt() throws Exception {
         return Integer.parseInt(next());
      }
      long nextLong() throws Exception {
         return Long.parseLong(next());
      }
      double nextDouble() throws Exception {
         return Double.parseDouble(next());
      }
   }

   public class Pair implements Comparable<Pair> {
      int ind;
      long value;
      double value2;
      Pair(int ii, long vv) {
         ind=ii;value=vv;
         value2=0.0;
      }
      public int compareTo(Pair o) {
         if (o.value == value)
            return Double.compare(value2,o.value);
         return Long.compare(value, o.value);
      }
   }
}


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.util.Iterator;
import java.io.BufferedWriter;
import java.util.Collection;
import java.util.Random;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.InputStream;

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

  static class TaskD {
    static final IntModular MOD = new IntModular();
    int n;
    int m;
    int[] end1;
    int[] end2;
    int res;
    boolean[] visited;
    BidirectionalGraph graph;
    IntArrayList points;
    IntArrayList pointCounts;

    public void solve(int testNumber, QuickScanner in, QuickWriter out) {
      n = in.nextInt();
      m = in.nextInt();
      end1 = new int[m];
      end2 = new int[m];
      in.nextInts(m, end1, end2);
      initPoints();
      initGraph();
      res = 0;
      visited = new boolean[points.size];
      for (int i = 0; i < points.size; ++i) {
        res = MOD.add(res, MOD.mul(pointCounts.get(i), dfs(i)));
      }
      out.println(res);
    }

    int dfs(int u) {
      visited[u] = true;
      int res = pointCounts.get(u);
      for (int v : graph.outNodes(u))
        if (!visited[v]) {
          res = MOD.add(res, dfs(v));
        }
      visited[u] = false;
      return res;
    }

    void initGraph() {
      graph = new BidirectionalGraph(points.size, points.size + m);
      points.forEach((point) -> {
        if (point > 1) {
          graph.add(points.lowerBound(point), points.lowerBound(point >> 1));
        }
      });
      for (int i = 0; i < m; ++i) {
        graph.add(points.lowerBound(end1[i]), points.lowerBound(end2[i]));
      }
    }

    void initPoints() {
      points = new IntArrayList();
      for (int i = 0; i < m; ++i) {
        addKeyPoints(end1[i]);
        addKeyPoints(end2[i]);
      }
      points.sortAndUnique();
      if (points.isEmpty()) {
        points.add(1);
      }
      pointCounts = new IntArrayList(points.size);
      for (int point : points) {
        int cnt = 1;
        if (!points.binarySearch(point << 1)) {
          cnt += calcSubtree(point << 1);
        }
        if (!points.binarySearch((point << 1) | 1)) {
          cnt += calcSubtree((point << 1) | 1);
        }
        pointCounts.add(cnt);
      }
    }

    int calcSubtree(int x) {
      int lower = x, upper = x;
      int res = 0;
      for (; lower <= n; lower <<= 1, upper = (upper << 1) | 1) {
        res += Math.min(n, upper) - lower + 1;
        if (n <= upper) break;
      }
      return res;
    }

    void addKeyPoints(int x) {
      for (; x > 0; x >>= 1) points.add(x);
    }

  }

  static abstract class AbstractBidirectionalGraph extends AbstractDirectedGraph implements BidirectionalGraphInterface {
    public AbstractBidirectionalGraph() {
      super();
    }

    public AbstractBidirectionalGraph(int vertexCapacity, int edgeCapacity) {
      super(vertexCapacity, edgeCapacity << 1);
    }

    public AbstractBidirectionalGraph(int vertexCapacity, int edgeCapacity, boolean initialize) {
      super(vertexCapacity, edgeCapacity << 1, initialize);
    }

    public void add(int u, int v) {
      super.add(u, v);
      super.add(v, u);
    }

  }

  static class QuickWriter {
    private final PrintWriter writer;

    public QuickWriter(OutputStream outputStream) {
      this.writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
    }

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

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

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

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

  }

  static final class BidirectionalGraph extends AbstractBidirectionalGraph {
    public BidirectionalGraph() {
      super();
    }

    public BidirectionalGraph(int vertexCapacity, int edgeCapacity) {
      super(vertexCapacity, edgeCapacity);
    }

    public void createVertexStorage(int vertexCapacity) {
    }

    public void expandEdgeStorage(int edgeCapacity) {
    }

    public void initVertexStorage(int vertexCnt) {
    }

  }

  static class QuickScanner {
    private static final int BUFFER_SIZE = 1024;
    private InputStream stream;
    private byte[] buffer;
    private int currentPosition;
    private int numberOfChars;

    public QuickScanner(InputStream stream) {
      this.stream = stream;
      this.buffer = new byte[BUFFER_SIZE];
      this.currentPosition = 0;
      this.numberOfChars = 0;
    }

    public int nextInt() {
      int c = nextNonSpaceChar();
      boolean positive = true;
      if (c == '-') {
        positive = false;
        c = nextChar();
      }
      int res = 0;
      do {
        if (c < '0' || '9' < c) throw new RuntimeException();
        res = res * 10 + (c - '0');
        c = nextChar();
      } while (!isSpaceChar(c));
      return positive ? res : -res;
    }

    public void nextInts(int n, int[]... res) {
      int m = res.length;
      for (int i = 0; i < n; ++i)
        for (int j = 0; j < m; ++j) {
          res[j][i] = nextInt();
        }
    }

    public int nextNonSpaceChar() {
      int res = nextChar();
      for (; isSpaceChar(res) || res < 0; res = nextChar()) ;
      return res;
    }

    public int nextChar() {
      if (numberOfChars == -1) {
        throw new RuntimeException();
      }
      if (currentPosition >= numberOfChars) {
        currentPosition = 0;
        try {
          numberOfChars = stream.read(buffer);
        } catch (Exception e) {
          throw new RuntimeException(e);
        }
        if (numberOfChars <= 0) {
          return -1;
        }
      }
      return buffer[currentPosition++];
    }

    public boolean isSpaceChar(int c) {
      return c == ' ' || c == '\t' || isEndOfLineChar(c);
    }

    public boolean isEndOfLineChar(int c) {
      return c == '\n' || c == '\r' || c < 0;
    }

  }

  static interface IntCollection {
    int size();

    default boolean isEmpty() {
      return size() == 0;
    }

  }

  static class IntArrayList implements Displayable, IntCollection, Iterable<Integer> {
    private static final int[] EMPTY = {};
    public int[] values;
    public int size;

    public IntArrayList() {
      values = EMPTY;
      clear();
    }

    public IntArrayList(int capacity) {
      values = new int[IntUtils.nextPow2(capacity)];
      clear();
    }

    public IntArrayList(Collection<Integer> collection) {
      this(collection.size());
      addAll(collection);
    }

    public void clear() {
      size = 0;
    }

    public int size() {
      return size;
    }

    public void add(int value) {
      ensureCapacity(size + 1);
      addInternal(value);
    }

    public void addAll(Collection<Integer> values) {
      ensureCapacity(size + values.size());
      for (int value : values) {
        addInternal(value);
      }
    }

    public int get(int idx) {
      if (idx >= size) throw new ArrayIndexOutOfBoundsException();
      return values[idx];
    }

    public void sort() {
      IntArrayUtils.sort(values, 0, size);
    }

    public void unique() {
      size = IntArrayUtils.unique(values, 0, size);
    }

    public void sortAndUnique() {
      sort();
      unique();
    }

    public int lowerBound(int value) {
      return IntArrayUtils.lowerBound(values, 0, size, value);
    }

    public boolean binarySearch(int value) {
      int idx = lowerBound(value);
      return idx < size && get(idx) == value;
    }

    public void ensureCapacity(int capacity) {
      if (capacity <= values.length) return;
      int[] newValues = new int[IntUtils.nextPow2(capacity)];
      for (int i = 0; i < size; ++i) {
        newValues[i] = values[i];
      }
      values = newValues;
    }

    public Iterator<Integer> iterator() {
      return new Iterator<Integer>() {
        private int i = 0;

        public boolean hasNext() {
          return i < size;
        }

        public Integer next() {
          return values[i++];
        }
      };
    }

    private void addInternal(int value) {
      values[size++] = value;
    }

  }

  static class IntArrayUtils {
    private static final Random RANDOM = new Random(1000000007);

    public static int unique(int[] values, int fromIdx, int toIdx) {
      if (fromIdx == toIdx) return 0;
      int res = 1;
      for (int i = fromIdx + 1; i < toIdx; ++i) {
        if (values[i - 1] != values[i]) {
          values[fromIdx + res++] = values[i];
        }
      }
      return res;
    }

    public static void sort(int[] values, int fromIdx, int toIdx) {
      shuffle(values, fromIdx, toIdx);
      Arrays.sort(values, fromIdx, toIdx);
    }

    public static int lowerBound(int[] values, int fromIdx, int toIdx, int value) {
      int res = toIdx;
      for (int lower = fromIdx, upper = toIdx - 1; lower <= upper; ) {
        int medium = (lower + upper) >> 1;
        if (value <= values[medium]) {
          res = medium;
          upper = medium - 1;
        } else {
          lower = medium + 1;
        }
      }
      return res;
    }

    public static void swap(int[] values, int uIdx, int vIdx) {
      if (uIdx == vIdx) return;
      values[uIdx] ^= values[vIdx];
      values[vIdx] ^= values[uIdx];
      values[uIdx] ^= values[vIdx];
    }

    public static void shuffle(int[] values, int fromIdx, int toIdx) {
      for (int i = toIdx - fromIdx - 1; i > 0; --i) {
        swap(values, i + fromIdx, RANDOM.nextInt(i + 1) + fromIdx);
      }
    }

    public static int[] expand(int[] values, int newLength) {
      if (values != null && values.length >= newLength) return values;
      int[] res = new int[newLength];
      if (values == null) return res;
      for (int i = 0; i < values.length; ++i) res[i] = values[i];
      return res;
    }

  }

  static class IntUtils {
    public static boolean isPow2(int n) {
      return n > 0 && (n & (n - 1)) == 0;
    }

    public static int nextPow2(int n) {
      if (n < 1) return 1;
      return isPow2(n) ? n : Integer.highestOneBit(n) << 1;
    }

  }

  static interface DirectedGraphInterface {
  }

  static interface Displayable {
  }

  static abstract class AbstractDirectedGraph implements DirectedGraphInterface {
    protected int vertexCnt;
    protected int currentEdgeCnt;
    protected int[] fromIdx;
    protected int[] toIdx;
    protected int[] nextIn;
    protected int[] nextOut;
    protected int[] lastIn;
    protected int[] lastOut;
    protected int[] inDegree;
    protected int[] outDegree;

    public abstract void createVertexStorage(int vertexCapacity);

    public abstract void expandEdgeStorage(int edgeCapacity);

    public abstract void initVertexStorage(int vertexCnt);

    public AbstractDirectedGraph() {
    }

    public AbstractDirectedGraph(int vertexCapacity, int edgeCapacity) {
      this(vertexCapacity, edgeCapacity, true);
    }

    public AbstractDirectedGraph(int vertexCapacity, int edgeCapacity, boolean initialize) {
      ensureVertexCapacity(vertexCapacity);
      ensureEdgeCapacity(edgeCapacity);
      if (initialize) init(vertexCapacity);
    }

    public void init(int vertexCnt) {
      ensureVertexCapacity(vertexCnt);
      this.vertexCnt = vertexCnt;
      currentEdgeCnt = 0;
      Arrays.fill(inDegree, 0, vertexCnt, 0);
      Arrays.fill(outDegree, 0, vertexCnt, 0);
      Arrays.fill(lastIn, 0, vertexCnt, -1);
      Arrays.fill(lastOut, 0, vertexCnt, -1);
      initVertexStorage(vertexCnt);
    }

    public void add(int fromIdx, int toIdx) {
      ensureEdgeCapacity(currentEdgeCnt + 1);
      this.fromIdx[currentEdgeCnt] = fromIdx;
      this.toIdx[currentEdgeCnt] = toIdx;
      ++outDegree[fromIdx];
      ++inDegree[toIdx];
      nextOut[currentEdgeCnt] = lastOut[fromIdx];
      lastOut[fromIdx] = currentEdgeCnt;
      nextIn[currentEdgeCnt] = lastIn[toIdx];
      lastIn[toIdx] = currentEdgeCnt;
      ++currentEdgeCnt;
    }

    public int nextOut(int edgeIdx) {
      return nextOut[edgeIdx];
    }

    public Iterable<Integer> outNodes(int nodeIdx) {
      return () -> new Iterator<Integer>() {
        private int edgeIdx = lastOut[nodeIdx];

        public boolean hasNext() {
          return edgeIdx >= 0;
        }

        public Integer next() {
          int res = toIdx[edgeIdx];
          edgeIdx = nextOut(edgeIdx);
          return res;
        }
      };
    }

    private void ensureVertexCapacity(int vertexCapacity) {
      if (lastIn != null && lastIn.length >= vertexCapacity) return;
      int capacity = IntUtils.nextPow2(vertexCapacity);
      lastIn = new int[capacity];
      lastOut = new int[capacity];
      inDegree = new int[capacity];
      outDegree = new int[capacity];
      createVertexStorage(capacity);
    }

    private void ensureEdgeCapacity(int edgeCapacity) {
      if (fromIdx != null && fromIdx.length >= edgeCapacity) return;
      int capacity = IntUtils.nextPow2(edgeCapacity);
      fromIdx = IntArrayUtils.expand(fromIdx, capacity);
      toIdx = IntArrayUtils.expand(toIdx, capacity);
      nextIn = IntArrayUtils.expand(nextIn, capacity);
      nextOut = IntArrayUtils.expand(nextOut, capacity);
      expandEdgeStorage(capacity);
    }

  }

  static interface BidirectionalGraphInterface extends DirectedGraphInterface {
  }

  static class IntModular {
    private static final int MOD = 1000000007;
    public final int mod;
    private final int[] x;

    public IntModular() {
      this(MOD);
    }

    public IntModular(int mod) {
      this.mod = mod;
      this.x = new int[2];
    }

    public int add(int a, int b) {
      return fix(a + b);
    }

    public int fix(int a) {
      a = slightFix(a);
      return 0 <= a && a < mod ? a : slightFix(a % mod);
    }

    public int mul(int a, int b) {
      return a > 0
          ? (b < mod / a ? a * b : (int) ((long) a * b % mod))
          : 0;
    }

    private int slightFix(int a) {
      return a >= mod
          ? a - mod
          : a < 0 ? a + mod : a;
    }

  }
}


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

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

    int N = 300;
    int MOD = (int) 1e9 + 7;

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

    int[] num = new int[N];
    List<Integer>[] G = new List[N];

    int tot = 0;
    boolean[] vis = new boolean[N];

    void solve() {
        int n = in.nextInt(), m = in.nextInt();
        int[] fr = new int[m], to = new int[m];
        for (int i = 0; i < m; i++) {
            fr[i] = in.nextInt();
            to[i] = in.nextInt();
        }

        int d = 0;
        while ((1 << d) <= n) d++;

        getId(1);
        for (int i = 0; i < m; i++) {
            int u = fr[i];
            while (u > 0) {
                getId(u);
                u >>= 1;
            }
            u = to[i];
            while (u > 0) {
                getId(u);
                u >>= 1;
            }
        }

        for (int i = 0; i < N; i++) G[i] = new ArrayList<>();
        for (int u : map.keySet()) {
            int id = map.get(u);
            if (u > 1) {
                addEdge(getId(u), getId(u >> 1));
            }
            num[id] = calcSize(u, n, d);
        }

        dfs(0, -1);

        for (int i = 0; i < m; i++) {
            addEdge(getId(fr[i]), getId(to[i]));
        }

        int res = 0;
        for (int i = 0; i < map.size(); i++) {
            tot = 0;
            dfs(i);
            res = (int) ((res + (long) tot * num[i] % MOD) % MOD);
        }
        out.println(res);
    }

    int getId(int x) {
        if (!map.containsKey(x)) map.put(x, map.size());
        return map.get(x);
    }

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

    int calcSize(int u, int n, int d) {
        int t = u, c = 0;
        while (t > 0) {
            c++;
            t >>= 1;
        }
        int sz = (1 << (d - c + 1)) - 1;
        t = c;
        while (t < d) {
            t++;
            u = u << 1 | 1;
        }
        return sz - Math.max(0, Math.min(u - n, 1 << (d - c)));
    }

    void dfs(int u, int p) {
        for (int v : G[u]) {
            if (v != p) {
                num[u] -= num[v];
                dfs(v, u);
            }
        }
    }

    void dfs(int u) {
        tot = (tot + num[u]) % MOD;
        vis[u] = true;
        for (int v : G[u]) {
            if (!vis[v]) dfs(v);
        }
        vis[u] = false;
    }

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

    static FastScanner in;
    static PrintWriter out;

    static class FastScanner {
        BufferedReader in;
        StringTokenizer st;

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

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

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

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

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


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

public class MainD {
	static final StdIn in = new StdIn();
	static final PrintWriter out = new PrintWriter(System.out);
	static final long M=(long)1e9+7;
	static int n=in.nextInt(), m=in.nextInt();
	static Map<Integer, Node> graph = new HashMap<Integer, Node>();

	public static void main(String[] args) {
		addNode(1);
		for(int i=0; i<m; ++i) {
			int u=in.nextInt(), v=in.nextInt();
			addNode(u).adj.add(v);
			addNode(v).adj.add(u);
		}
		for(Map.Entry<Integer, Node> nodeEntry : graph.entrySet()) {
			Node u=nodeEntry.getValue();
			for(int i=u.adj.size()-1; i>=0; --i) {
				if(!graph.containsKey(u.adj.get(i))) {
					u.s+=sts(u.adj.get(i));
					u.adj.remove(i);
				}
			}
		}
		long ans=0;
		for(Map.Entry<Integer, Node> nodeEntry : graph.entrySet())
			ans=(dfs(nodeEntry.getKey(), 0)+ans)%M;
		out.println(ans);
		out.close();
	}

	static Node addNode(int u) {
		if(u<=0)
			return null;
		Node node = graph.get(u);
		if(node!=null)
			return node;
		node = new Node();
		if(u>1)
			node.adj.add(u/2);
		if(u*2<=n)
			node.adj.add(u*2);
		if(u*2+1<=n)
			node.adj.add(u*2+1);
		graph.put(u, node);
		addNode(u/2);
		return node;
	}

	static long sts(int u) {
		long res=0;
		int l=u, r=u;
		while(r<=n) {
			res+=r-l+1;
			l=2*l;
			r=2*r+1;
		}
		return (res+Math.min(r, n)-Math.min(l, n+1)+1)%M;
	}

	static long dfs(int u, long ps) {
		Node node=graph.get(u);
		if(ps==0)
			ps=node.s;
		node.active=true;
		long res=ps*node.s;
		for(int v : node.adj)
			if(!graph.get(v).active)
				res+=dfs(v, ps);
		node.active=false;
		return res;
	}

	static class Node {
		List<Integer> adj = new ArrayList<Integer>();
		long s=1;
		boolean active;
	}

	interface Input {
		public String next();
		public String nextLine();
		public int nextInt();
		public long nextLong();
		public double nextDouble();
	}
	static class StdIn implements Input {
		final private int BUFFER_SIZE = 1 << 16;
		private DataInputStream din;
		private byte[] buffer;
		private int bufferPointer, bytesRead;
		public StdIn() {
			din = new DataInputStream(System.in);
			buffer = new byte[BUFFER_SIZE];
			bufferPointer = bytesRead = 0;
		}
		public StdIn(InputStream in) {
			try{
				din = new DataInputStream(in);
			} catch(Exception e) {
				throw new RuntimeException();
			}
			buffer = new byte[BUFFER_SIZE];
			bufferPointer = bytesRead = 0;
		}
		public String next() {
			int c;
			while((c=read())!=-1&&(c==' '||c=='\n'||c=='\r'));
			StringBuilder s = new StringBuilder();
			while (c != -1)
			{
				if (c == ' ' || c == '\n'||c=='\r')
					break;
				s.append((char)c);
				c=read();
			}
			return s.toString();
		}
		public String nextLine() {
			int c;
			while((c=read())!=-1&&(c==' '||c=='\n'||c=='\r'));
			StringBuilder s = new StringBuilder();
			while (c != -1)
			{
				if (c == '\n'||c=='\r')
					break;
				s.append((char)c);
				c = read();
			}
			return s.toString();
		}
		public int nextInt() {
			int ret = 0;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();
			do
				ret = ret * 10 + c - '0';
			while ((c = read()) >= '0' && c <= '9');

			if (neg)
				return -ret;
			return ret;
		}
		public int[] readIntArray(int n) {
			int[] ar = new int[n];
			for(int i=0; i<n; ++i)
				ar[i]=nextInt();
			return ar;
		}
		public long nextLong() {
			long ret = 0;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();
			do
				ret = ret * 10 + c - '0';
			while ((c = read()) >= '0' && c <= '9');
			if (neg)
				return -ret;
			return ret;
		}
		public long[] readLongArray(int n) {
			long[] ar = new long[n];
			for(int i=0; i<n; ++i)
				ar[i]=nextLong();
			return ar;
		}
		public double nextDouble() {
			double ret = 0, div = 1;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();
			do
				ret = ret * 10 + c - '0';
			while ((c = read()) >= '0' && c <= '9');
			if (c == '.')
				while ((c = read()) >= '0' && c <= '9')
					ret += (c - '0') / (div *= 10);
			if (neg)
				return -ret;
			return ret;
		}
		private void fillBuffer() throws IOException {
			bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
			if (bytesRead == -1)
				buffer[0] = -1;
		}
		private byte read() {
			try{
				if (bufferPointer == bytesRead)
					fillBuffer();
				return buffer[bufferPointer++];
			} catch(IOException e) {
				throw new RuntimeException();
			}
		}
		public void close() throws IOException {
			if (din == null)
				return;
			din.close();
		}
	}
}


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

public class D {
	InputStream is;
	PrintWriter out;
//	String INPUT = "3 1 2 3";
//	String INPUT = "2 1 1 2";
//	String INPUT = "4 1 2 3";
//	String INPUT = "5 1 4 5";
//	String INPUT = "5 1 3 5";
//	String INPUT = "4 1 1 3";
//	String INPUT = "4 2\r\n" +
//			"2 3 1 2 ";
//	String INPUT = "4 2\r\n" +
//			"2 4 1 4 ";
	String INPUT = "";

	//    A1 A2 A3 ...
	// A0              An
	// A0*(A1+...+An)
	// A1*(A2+...+An)
	// ((A0+..+An)^2-A0^2-..-An^2)/2

	void solve()
	{
		int n = ni(), m = ni();
		int[][] ps = new int[m][];
		for(int i = 0;i < m;i++){
			ps[i] = na(2);
		}
//		for(int i = 1;i <= n;i++)tr(i, n, count(i,n));
		int mod = 1000000007;
		long ans = (long)n*n % mod;
		for(int i = 1;i < 1<<m;i++){
			int[] inds = new int[Integer.bitCount(i)];
			int p = 0;
			for(int j = 0;j < m;j++){
				if(i<<~j<0)inds[p++] = j;
			}
			int o = Integer.bitCount(i);
			do{
				// 0:0->1, 1:1->0
				for(int ptn = 0;ptn < 1<<o;ptn++){
					ans += go(inds, ptn, ps, n);
					ans %= mod;
//					tr("ans", i, inds, ptn, ans);
				}
			}while(nextPermutation(inds));
		}
		out.println(ans % mod);
	}

	long go(int[] inds, int ptn, int[][] ps, int n)
	{
		// collide?
		int[][] paths = new int[2*(inds.length-1)][];
		int p = 0;
		for(int i = 0;i < inds.length-1;i++){
			int f = ptn<<~i>=0 ? ps[inds[i]][1] : ps[inds[i]][0];
			int t = ptn<<~(i+1)>=0 ? ps[inds[i+1]][0] : ps[inds[i+1]][1];
			int lca = lca(f, t);
			paths[p++] = new int[]{f, lca};
			if(lca != t){
				int clca = t/(Integer.highestOneBit(t)/Integer.highestOneBit(lca)/2);
				paths[p++] = new int[]{t, clca};
			}
		}
		for(int i = 0;i < p;i++){
			for(int j = i+1;j < p;j++){
				if(col(paths[i], paths[j]))return 0;
			}
		}
//		tr("UM");
		int[] st = {
				ptn<<~0>=0 ? ps[inds[0]][0] : ps[inds[0]][1],
				ptn<<~(inds.length-1)>=0 ? ps[inds[inds.length-1]][1] : ps[inds[inds.length-1]][0]
		};
		if(st[0] == st[1])return 0;
//		tr("OK", st);
		int[] tops = new int[2];
		for(int j = 0;j < 2;j++){
			int top = 0;
			for(int i = 0;i < p;i++){
				int lcad = lca(st[j], paths[i][0]);
				if(Integer.highestOneBit(lcad) >= Integer.highestOneBit(paths[i][1])){
					top = Math.max(top, lcad);
				}
			}
			if(top == st[j])return 0; // collide

			if(top == 0){
				top = 1;
			}else{
				int otop = top;
				top = st[j] / (Integer.highestOneBit(st[j]) / Integer.highestOneBit(top) / 2);
				assert top / 2 == otop;
			}
			tops[j] = top;
		}
//		tr(st, tops);
		if(tops[0] == tops[1]){
			return calc(tops[0], paths, p, n, st[0], st[1]);
		}else{
			return (long)all(tops[0], paths, p, n, st[0]) *
					all(tops[1], paths, p, n, st[1]);
		}
	}

	int count(int x, int n)
	{
		int first = Integer.highestOneBit(n) / Integer.highestOneBit(x) * x;
		int last = Integer.highestOneBit(n) / Integer.highestOneBit(x) * (x+1);
		int base = Integer.highestOneBit(n) / Integer.highestOneBit(x) - 1;
		return base + Math.max(0, Math.min(last-first, n-first+1));
	}

	int all(int top, int[][] paths, int p, int n, int tar)
	{
		int[] lroot = new int[p];
		int q = 0;
		for(int i = 0;i < p;i++){
			int llca = lca(paths[i][1], tar);
			if(Integer.highestOneBit(llca) < Integer.highestOneBit(top))continue;
			lroot[q++] = paths[i][1];
		}
		boolean[] ng = new boolean[q];
		for(int i = 0;i < q;i++){
			for(int k = 0;k < q;k++){
				if(i == k)continue;
				if(lca(lroot[i], lroot[k]) == lroot[k]){
					ng[i] = true;
				}
			}
		}
		int all = count(top, n);
		for(int i = 0;i < q;i++){
			if(!ng[i]){
				all -= count(lroot[i], n);
			}
		}
		return all;
	}

	long calc(int top, int[][] paths, int p, int n, int t1, int t2)
	{
		int[] lroot = new int[p];
		int q = 0;
		for(int i = 0;i < p;i++){
			int llca = lca(paths[i][1], t1);
			if(Integer.highestOneBit(llca) < Integer.highestOneBit(top))continue;
			lroot[q++] = paths[i][1];
		}
		boolean[] ng = new boolean[q];
		for(int i = 0;i < q;i++){
			for(int k = 0;k < q;k++){
				if(i == k)continue;
				if(lca(lroot[i], lroot[k]) == lroot[k]){
					ng[i] = true;
				}
			}
		}
		int[] route = new int[100];
		int tl = lca(t1, t2);
		int r = 0;
		for(int z = t1;z != tl;z /= 2){
			route[r++] = z;
		}
		int or = r;
		for(int z = t2;z != tl;z /= 2){
			route[r++] = z;
		}
		route[r++] = tl;
		for(int i = or, j = r-1;i < j;i++,j--){
			int d = route[i]; route[i] = route[j]; route[j] = d;
		}
		route = Arrays.copyOf(route, r);
		int[] has = new int[r];
		for(int i = 0;i < r;i++){
			has[i] = count(route[i], n);
		}
		for(int i = or-1;i >= 1;i--){
			has[i] -= has[i-1];
		}
		for(int i = or+1;i < r-1;i++){
			has[i] -= has[i+1];
		}
		for(int i = 0;i < q;i++){
			if(!ng[i] && lca(lroot[i], tl) == tl){
				int hit = lca(lroot[i], t1);
				if(hit == tl)hit = lca(lroot[i], t2);
				for(int j = 0;j < r;j++){
					if(route[j] == hit){
						has[j] -= count(lroot[i], n);
						break;
					}
				}
			}
		}
		if(tl != t1 && tl != t2){
			has[or] = count(top, n) - count(tl, n) + 1;

			for(int i = 0;i < q;i++){
				if(!ng[i] && lca(lroot[i], tl) != tl){
					has[or] -= count(lroot[i], n);
				}
			}
		}else{
			int tlch = route[or == 0 ? 1 : r - 2];
			has[or] = count(top, n) - count(tlch, n);
			for(int i = 0;i < q;i++){
				if(!ng[i] && lca(lroot[i], tlch) != tlch){
					has[or] -= count(lroot[i], n);
				}
			}
		}
//		tr("route", route);
//		tr("has", has, lroot);
		long s1 = 0;
		long s2 = 0;
		for(int v : has){
			s1 += v;
			s2 += (long)v*v;
		}
		return (s1*s1-s2)/2;
	}

	public static int lca(long x, long y)
	{
		long xx = x<<Long.numberOfLeadingZeros(x);
		long yy = y<<Long.numberOfLeadingZeros(y);
		return (int)(x>>>Math.max(Long.numberOfLeadingZeros(Math.min(x, y)), 64-Long.numberOfLeadingZeros(xx^yy))-Long.numberOfLeadingZeros(x));
	}

	boolean col(int[] a, int[] b)
	{
		int l = lca(a[0], b[0]);
		if(Integer.highestOneBit(a[1]) <= Integer.highestOneBit(l) && Integer.highestOneBit(b[1]) <= Integer.highestOneBit(l)){
			return true;
		}else{
			return false;
		}
	}

	static boolean nextPermutation(int[] src) {
		int i;
		for (i = src.length - 2; i >= 0 && src[i] > src[i + 1]; i--)
			;
		if (i == -1)
			return false;
		int j;
		for (j = i + 1; j < src.length && src[i] < src[j]; j++)
			;
		int d = src[i];
		src[i] = src[j - 1];
		src[j - 1] = d;
		for (int p = i + 1, q = src.length - 1; p < q; p++, q--) {
			d = src[p];
			src[p] = src[q];
			src[q] = d;
		}
		return true;
	}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

public class Main {

	static final int MOD = 1000000007;

    public static int count(int height,int width) {

        boolean[][] field = new boolean[height][width];
        for (int i = 0; i < height / 2; ++i) {
            for (int j = 0; j < width / 2; ++j) {
                field[i * 2][j * 2] = false;
                field[i * 2][j * 2 + 1] = false;
                field[i * 2 + 1][j * 2] = false;
                field[i * 2 + 1][j * 2 + 1] = false;
            }
        }
        int[][][][] res = new int[2][2][width][width];
        int totalRes = 0;
        for (int row = 0; row < height; ++row) {
            int[][][][] newRes = new int[2][2][width][width];
            for (int firstDecreased = 0; firstDecreased < 2; ++firstDecreased)
                for (int lastDecreased = 0; lastDecreased < 2; ++lastDecreased)
                    for (int firstCol = 0; firstCol < width; ++firstCol)
                        for (int lastCol = firstCol; lastCol < width; ++lastCol) {
                            int cur = res[firstDecreased][lastDecreased][firstCol][lastCol];
                            if (cur == 0) continue;
                            for (int newFirstDecreased = firstDecreased; newFirstDecreased < 2; ++newFirstDecreased)
                                for (int newLastDecreased = lastDecreased; newLastDecreased < 2; ++newLastDecreased) {
                                    int newFirstCol;
                                    if (newFirstDecreased == 0)
                                        newFirstCol = firstCol;
                                    else if (firstDecreased == 0)
                                        newFirstCol = firstCol + 1;
                                    else
                                        newFirstCol = firstCol;
                                    int newLastCol;
                                    if (newLastDecreased == 0)
                                        newLastCol = lastCol;
                                    else if (lastDecreased == 0)
                                        newLastCol = lastCol - 1;
                                    else
                                        newLastCol = lastCol;
                                    if (newFirstCol > newLastCol)
                                        continue;
                                    int[] arr = newRes[newFirstDecreased][newLastDecreased][newFirstCol];
                                    arr[newLastCol] += cur;
                                    if (arr[newLastCol] >= MOD) arr[newLastCol] -= MOD;
                                }
                        }

            for (int firstDecreased = 0; firstDecreased < 2; ++firstDecreased)
                for (int lastDecreased = 0; lastDecreased < 2; ++lastDecreased) {
                    int[][] arr = newRes[firstDecreased][lastDecreased];
                    if (firstDecreased == 0 && lastDecreased == 1) {
                        {
                            int lastDelta = lastDecreased == 0 ? 1 : -1;
                            int lastMin = lastDelta == 1 ? 0 : width - 1;
                            int lastMax = lastDelta == 1 ? width : -1;
                            for (int lastCol = lastMin; lastCol != lastMax; lastCol += lastDelta) {
                                for (int firstCol = 0; firstCol <= lastCol; ++firstCol) {
                                    int cur = arr[firstCol][lastCol];
                                    if (cur == 0) continue;
                                    int newLastCol = lastCol + lastDelta;
                                    if (newLastCol >= firstCol && newLastCol < width) {
                                        arr[firstCol][newLastCol] += cur;
                                        if (arr[firstCol][newLastCol] >= MOD) arr[firstCol][newLastCol] -= MOD;
                                    }
                                }
                            }
                        }
                        {
                            int firstDelta = firstDecreased == 0 ? -1 : 1;
                            int firstMin = firstDelta == 1 ? 0 : width - 1;
                            int firstMax = firstDelta == 1 ? width : -1;
                            for (int firstCol = firstMin; firstCol != firstMax; firstCol += firstDelta) {
                                for (int lastCol = firstCol; lastCol < width; ++lastCol) {
                                    int cur = arr[firstCol][lastCol];
                                    if (cur == 0) continue;
                                    int newFirstCol = firstCol + firstDelta;
                                    if (newFirstCol >= 0 && newFirstCol <= lastCol) {
                                        arr[newFirstCol][lastCol] += cur;
                                        if (arr[newFirstCol][lastCol] >= MOD) arr[newFirstCol][lastCol] -= MOD;
                                    }
                                }
                            }
                        }
                    } else {
                        {
                            int firstDelta = firstDecreased == 0 ? -1 : 1;
                            int firstMin = firstDelta == 1 ? 0 : width - 1;
                            int firstMax = firstDelta == 1 ? width : -1;
                            for (int firstCol = firstMin; firstCol != firstMax; firstCol += firstDelta) {
                                for (int lastCol = firstCol; lastCol < width; ++lastCol) {
                                    int cur = arr[firstCol][lastCol];
                                    if (cur == 0) continue;
                                    int newFirstCol = firstCol + firstDelta;
                                    if (newFirstCol >= 0 && newFirstCol <= lastCol) {
                                        arr[newFirstCol][lastCol] += cur;
                                        if (arr[newFirstCol][lastCol] >= MOD) arr[newFirstCol][lastCol] -= MOD;
                                    }
                                }
                            }
                        }
                        {
                            int lastDelta = lastDecreased == 0 ? 1 : -1;
                            int lastMin = lastDelta == 1 ? 0 : width - 1;
                            int lastMax = lastDelta == 1 ? width : -1;
                            for (int lastCol = lastMin; lastCol != lastMax; lastCol += lastDelta) {
                                for (int firstCol = 0; firstCol <= lastCol; ++firstCol) {
                                    int cur = arr[firstCol][lastCol];
                                    if (cur == 0) continue;
                                    int newLastCol = lastCol + lastDelta;
                                    if (newLastCol >= firstCol && newLastCol < width) {
                                        arr[firstCol][newLastCol] += cur;
                                        if (arr[firstCol][newLastCol] >= MOD) arr[firstCol][newLastCol] -= MOD;
                                    }
                                }
                            }
                        }
                    }
                }

            for (int firstCol = 0; firstCol < width; ++firstCol) {
                boolean ok = true;
                for (int lastCol = firstCol; lastCol < width; ++lastCol) {
                    if (field[row][lastCol])
                        ok = false;
                    if (!ok) {
                        for (int firstDecreased = 0; firstDecreased < 2; ++firstDecreased)
                            for (int lastDecreased = 0; lastDecreased < 2; ++lastDecreased)
                                newRes[firstDecreased][lastDecreased][firstCol][lastCol] = 0;
                   } else {
                        newRes[0][0][firstCol][lastCol] += 1;
                        if (newRes[0][0][firstCol][lastCol] >= MOD) newRes[0][0][firstCol][lastCol] -= MOD;
                    }
                }
            }

            res = newRes;
            for (int firstDecreased = 0; firstDecreased < 2; ++firstDecreased)
                for (int lastDecreased = 0; lastDecreased < 2; ++lastDecreased)
                    for (int firstCol = 0; firstCol < width; ++firstCol)
                        for (int lastCol = firstCol; lastCol < width; ++lastCol) {
                            totalRes += res[firstDecreased][lastDecreased][firstCol][lastCol];
                            if (totalRes >= MOD) totalRes -= MOD;
                        }
        }
        return totalRes;
    }
	public static void main(String args[]){
	    Scanner scan = new Scanner(System.in);
	    int n=scan.nextInt();
	    int m=scan.nextInt();
	    System.out.println(count(n, m));
	}
}


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.*;
import java.util.*;

public class Solution {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner in = new Scanner(new BufferedReader(new InputStreamReader(System.in)));
		int n = in.nextInt();
		int x[] = new int[n], y[] = new int[n], t = 0;
		List<Integer> s = new ArrayList<Integer>();
		for(int i = 0; i < n; i++) {
			x[i] = in.nextInt();
			y[i] = in.nextInt();
			if(x[i] < x[t])
				t = i;
			s.add(i);
		}
		System.out.print(t + 1 + " ");
		s.remove(new Integer(t));
		String str = in.next();
		double ang = Math.PI / 2 - 1E-10;
		for(int i = 0; i < str.length(); i++) {
			double m = 4;
			int im = -1, factor = (str.charAt(i) == 'L') ? 1 : -1;
			for(int j : s) {
				double a = dif(Math.atan2(y[j] - y[t], x[j] - x[t]), ang) * factor;
				if(a < m) {
					m = a;
					im = j;
				}
			}
			s.remove(new Integer(im));
			ang = Math.atan2(y[im] - y[t], x[im] - x[t]);
			t = im;
			System.out.print(t + 1 + " ");
		}
		System.out.print(s.remove(0) + 1 + " ");
		System.out.println();
		in.close();

	}

	private static double dif(double a1, double a2) {
		double d = a1 - a2;
		while(d > Math.PI)
			d -= 2 * Math.PI;
		while(d < -Math.PI)
			d += 2 * Math.PI;
		return d;
	}

}


import static java.lang.Double.parseDouble;
import static java.lang.Integer.parseInt;
import static java.lang.Long.parseLong;
import static java.lang.System.exit;

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

public class F {

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

	static void solve() throws Exception {
		int n = nextInt();
		int d = nextInt();
		int mod = nextInt();
		if (n == 1) {
			out.print('1');
			return;
		}
		int fracs[] = new int[d + 2];
		for (int i = 1; i < fracs.length; i++) {
			fracs[i] = BigInteger.valueOf(i).modInverse(BigInteger.valueOf(mod)).intValue();
		}
		int maxsize = n;
		int cnts[] = new int[maxsize + 1];
		cnts[1] = 1;
		int cnts2[][][] = new int[maxsize + 1][d + 1][maxsize + 1];
		cnts2[0][0][1] = 1;
		for (int lastsize = 0; lastsize < (n - 1) / 2; lastsize++) {
			int nlastsize = lastsize + 1;
			int ccnt = cnts[nlastsize];
			int ccnt2[][] = cnts2[lastsize];
			int ncnt2[][] = cnts2[nlastsize];
			for (int ctrees = 0; ctrees <= d; ctrees++) {
				for (int csize = 1; csize <= maxsize; csize++) {
					int cur = ccnt2[ctrees][csize];
//					if (cur != 0) {
//						System.err.println(csize + " " + ctrees + " " + lastsize + " -> " + cur);
//					}
					for (int i = 0, ntrees = ctrees, nsize = csize;
						ntrees <= d && nsize <= maxsize;
						++i, ++ntrees, nsize += nlastsize) {
						ncnt2[ntrees][nsize] += cur;
						if (ncnt2[ntrees][nsize] >= mod) {
							ncnt2[ntrees][nsize] -= mod;
						}
						cur = (int) ((long) cur * (ccnt + i) % mod * fracs[i + 1] % mod);
					}
				}
			}
			if (nlastsize + 1 <= maxsize) {
				cnts[nlastsize + 1] = ncnt2[d - 1][nlastsize + 1];
			}
		}
		int ans = 0;
		if (n % 2 == 0) {
			ans = (int) ((long) cnts[n / 2] * (cnts[n / 2] + 1) % mod * fracs[2] % mod);
		}
		ans = (ans + cnts2[(n - 1) / 2][d][n]) % mod;
		out.print(ans);
	}

	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));
			solve();
			in.close();
			out.close();
		} catch (Throwable e) {
			e.printStackTrace();
			exit(1);
		}
	}
}


import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Arrays;
import java.io.BufferedWriter;
import java.util.InputMismatchException;
import java.util.ArrayList;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.Queue;
import java.util.LinkedList;
import java.util.Collection;
import java.io.InputStream;

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

class TaskD {
    AhoCorasickDataStructure ds;
    int [][][] dp;
    String s1, s2;

    int go(int i, int j, int state) {
        if(dp[i][j][state] == -1) {
            dp[i][j][state] = -100000;
            if(!ds.found[state]) {
                if(i >= s1.length() || j >= s2.length()) dp[i][j][state] = 0;
                else {
                    dp[i][j][state] = Math.max(go(i + 1, j, state), go(i, j + 1, state));
                    if(s1.charAt(i) == s2.charAt(j))
                        dp[i][j][state] = Math.max(dp[i][j][state], go(i + 1, j + 1, ds.trans[state][s1.charAt(i)- 'A']) + 1);
                }
            }
        }
        return dp[i][j][state];
    }

    public void solve(int testNumber, InReader in, OutputWriter out) {
        s1 = in.readString();
        s2 = in.readString();
        String virus = in.readString();
        ds = new AhoCorasickDataStructure(26, 'A');
        ds.add(virus, 0);
        ds.bfs();
        ds.makeTrans();
        dp = new int[s1.length() + 1][s2.length() + 1][virus.length() + 1];
        ArrayUtils.fill3d(dp, -1);

        /*for (int i = 0; i <= s1.length(); i++) {
            for (int j = 0; j <= s2.length(); j++) {
                for (int state = 0; state < virus.length(); state++) {
                    if(i == 0 || j == 0 || ds.found[state]) {
                        dp[i][j][state] = 0;
                        continue;
                    }
                    dp[i][j][state] = Math.max(Math.max(dp[i - 1][j][state], dp[i][j - 1][state]), dp[i][j][state]);
                    if(s1.charAt(i - 1) == s2.charAt(j - 1) && ds.trans[state][s1.charAt(i - 1) - 'A'] != virus.length()) {
                        dp[i][j][ds.trans[state][s1.charAt(i - 1) - 'A']] = Math.max(dp[i - 1][j - 1][state] + 1, dp[i][j][ds.trans[state][s1.charAt(i - 1) - 'A']]);
                        //System.out.println("updated " + i + "  "+ j + "  "+ state + " changed to " + dp[i][j][ds.trans[state][s1.charAt(i - 1) - 'A']]);
                    }
                }
            }
        }
        for (int i = 0; i < s1.length() + 1; i++) {
            System.out.println(Arrays.deepToString(dp[i]));
        } */
        int i = 0, j = 0, state = 0;
        ArrayList<Character> ans = new ArrayList<Character>();
        while (i < s1.length() && j < s2.length()) {
            if(go(i, j, state) == go(i + 1, j ,state)) i++;
            else if(go(i, j, state) == go(i, j + 1, state)) j++;
            else {
                ans.add(s1.charAt(i));
                state = ds.trans[state][s1.charAt(i) - 'A'];
                i++;
                j++;
            }
        }
        if(ans.size() == 0) out.printLine(0);
        else for(char c : ans) out.print(c);

        //System.out.println(dp[s1.length()][s2.length()]);
    }
}

class AhoCorasickDataStructure {
    public int[][] trans;
    Node root;
    int stateCount;
    public boolean[] found;
    int alphabetSize;
    char zero;
    public int[] counts;
    int strCount;
    Node[] getNode;

    public AhoCorasickDataStructure(int size, char zero) {
        this.alphabetSize = size;
        this.zero = zero;
        root = new Node(' ');
        strCount = 0;
    }

    public void add(String s, int id) {
        Node node = root;
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            int ind = c - zero;
            if (node.child[ind] == null) node.child[ind] = new Node(c);
            node.child[ind].parent = node;
            node = node.child[ind];
        }
        node.isEnd = true;
        node.endId = id;
        strCount++;
        //System.out.println("Add success");
    }

    public void bfs() {
        counts = new int[strCount];
        root.fall = root;
        Queue<Node> queue = new LinkedList<Node>();
        stateCount = 0;
        queue.offer(root);
        while (!queue.isEmpty()) {
            Node v = queue.poll();

            v.state = stateCount++;
            for (Node child : v.child)
                if (child != null) queue.offer(child);
            if (v == root) continue;
            Node fall = v.parent.fall;
            while (fall.child[v.c - zero] == null && fall != root) fall = fall.fall;
            v.fall = fall.child[v.c - zero];
            if (v.fall == null || v.fall == v) v.fall = root;
            else {
                Node temp = fall.child[v.c - zero];
                if(temp.isEnd) {
                    v.isEnd |= temp.isEnd;
                    //v.endId = temp.endId;
                }
            }
        }
        //System.out.println("bfs success");
    }

    public void makeTrans() {
        getNode = new Node[stateCount];
        trans = new int[stateCount][alphabetSize];
        found = new boolean[stateCount];
        Queue<Node> queue = new LinkedList<Node>();
        queue.offer(root);
        while(!queue.isEmpty()) {
            Node v = queue.poll();
            getNode[v.state] = v;
            if(v.isEnd) found[v.state] = true;
            for (int i = 0; i < v.child.length; i++) {
                Node node = v;
                if(v.child[i] != null) queue.offer(v.child[i]);
                while(node.child[i] == null && node != root) node = node.fall;
                if(node.child[i] != null) {
                    trans[v.state][i] = node.child[i].state;
                }
                else trans[v.state][i] = root.state;
            }
        }

    }

    class Node {
        char c;
        Node[] child;
        boolean isEnd;
        Node parent;
        Node fall;
        int state;
        int endId;

        Node(char c) {
            this.c = c;
            child = new Node[alphabetSize];
            isEnd = false;
            parent = null;
            fall = null;
            endId = -1;
        }
    }
}

class InReader {

    private InputStream stream;
    private byte[] buf = new byte[1024];
    private int curChar;
    private int numChars;
    private SpaceCharFilter filter;

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

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

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

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

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

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

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

    public interface SpaceCharFilter {
        public boolean isSpaceChar(int ch);
    }
}

class OutputWriter {
	private final PrintWriter writer;

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

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

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

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

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

}

class ArrayUtils {

	public static void fill2d(int [][] array, int value) {
		for (int i = 0;i < array .length ;i++)
			Arrays.fill(array [i], value);
	}

	public static void fill3d(int [][][] array ,int value) {
		for(int i = 0;i < array .length ;i ++) {
			fill2d(array [i],value );
		}
	}

    }


// Coached by rainboy
// https://codeforces.com/contest/1278/submission/67223059 (rainboy)
import java.io.*;
import java.util.*;

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

	static final int MD = 998244353;
	int d_, x_, y_;
	void gcd_(int a, int b) {
		if (b == 0) {
			d_ = a; x_ = 1; y_ = 0;
		} else {
			gcd_(b, a % b);
			int t = x_ - a / b * y_; x_ = y_; y_ = t;
		}
	}
	int inv(int a) {
		gcd_(a, MD);
		return x_ < 0 ? x_ + MD : x_;
	}
	void main() {
		int n = sc.nextInt();
		int m = sc.nextInt(), m_ = inv(m);
		int k = sc.nextInt();
		int[] dp = new int[k + 1]; dp[0] = 1;
		for (int h = 0; h < k; h++)
			for (int d = k - 1; d >= 0; d--)
				if (dp[d] != 0) {
					dp[d + 1] = (int) ((dp[d + 1] + (long) dp[d] * (n - d)) % MD);
					dp[d] = (int) ((long) dp[d] * d % MD);
				}
		long p = 1, ans = 0;
		for (int d = 1; d <= k; d++) {
			p = p * m_ % MD;
			ans = (ans + dp[d] * p) % MD;
		}
		println(ans);
	}
}


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

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

    static class Cards {
        long MOD = 998244353;

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            long N = in.nextInt();
            long M = in.nextInt();
            int K = in.nextInt();
            long mod = MathUtils.modFraction(1, M, MOD);
            long[] expect = new long[K + 1];
            expect[0] = 1;
            long[] poly = new long[K + 1];
            poly[0] = 1;
            long curExpect = 1;
            for (int k = 1; k <= K; k++) {
                curExpect *= (N - (k - 1));
                curExpect %= MOD;
                curExpect *= mod;
                curExpect %= MOD;
                for (int i = k; i >= 0; i--) {
                    poly[i] = (i > 0 ? poly[i - 1] : 0) + (-(k - 1)) * poly[i];
                    poly[i] = MathUtils.mod(poly[i], MOD);
                }
                expect[k] = curExpect;
                for (int i = k - 1; i >= 0; i--) {
                    expect[k] -= poly[i] * expect[i];
                    expect[k] = MathUtils.mod(expect[k], MOD);
                }
            }
            out.println(expect[K]);
        }

    }

    static class MathUtils {
        public static long inverse(long a, long mod) {
            long[] inv = extended_gcd(a, mod);
            if (inv[0] != 1) {
                return 0;
            } else {
                return (inv[1] + 2 * mod) % mod;
            }
        }

        public static long modFraction(long a, long b, long mod) {
            //a is numerator, b is denominator
            long invB = inverse(b, mod);
            if (invB == 0) {
                return -1;
            } else {
                return (invB * a) % mod;
            }
        }

        public static long[] extended_gcd(long a, long b) {
            //three numbers, first is gcd, second is x, third is y
            if (a == 0) {
                return new long[]{b, 0, 1};
            }
            long[] next = extended_gcd(b % a, a);
            long tempX = next[1];
            next[1] = next[2] - (b / a) * next[1];
            next[2] = tempX;
            return next;
        }

        public static long mod(long a, long mod) {
            return (a + (Math.abs(a) + mod - 1) / mod * mod) % mod;
        }

    }

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

    }
}