//package com.company;

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

public class Main {
    public static class Task {

        public class Maxflow {
            class Edge {
                int t, rev;
                long cap, f;
                public Edge(int t, int rev, long cap) {
                    this.t = t;
                    this.rev = rev;
                    this.cap = cap;
                }
            }
            public Maxflow(int n) {
                graph = new List[n];
                for (int i = 0; i < n; i++) {
                    graph[i] = new ArrayList<>();
                }
            }
            List<Edge>[] graph;
            void addEdge(int s, int t, long cap) {
                graph[s].add(new Edge(t, graph[t].size(), cap));
                graph[t].add(new Edge(s, graph[s].size() - 1, 0));
//                if (cap != Integer.MAX_VALUE)
//                System.err.println(s + " " + t + " " + cap);
            }

            boolean dinicBFS(int src, int dest, int[] dist) {
                Arrays.fill(dist, -1);
                dist[src] = 0;
                int[] Q = new int[graph.length];
                int sizeQ = 0;
                Q[sizeQ++] = src;
                for (int i = 0; i < sizeQ; i++) {
                    int u = Q[i];
                    for (Edge e: graph[u]) {
                        if (dist[e.t] < 0 && e.f < e.cap) {
                            dist[e.t] = dist[u] + 1;
                            Q[sizeQ++] = e.t;
                        }
                    }
                }
                return dist[dest] >= 0;
            }

            long dinicDFS(int[] ptr, int[] dist, int dest, int u, long f) {
                if (u == dest) return f;
                for (;ptr[u] < graph[u].size(); ++ptr[u]) {
                    Edge e =  graph[u].get(ptr[u]);
                    if (dist[e.t] == dist[u] + 1 && e.f < e.cap) {
                        long df = dinicDFS(ptr, dist, dest, e.t, Math.min(f, e.cap - e.f));
                        if (df > 0) {
                            e.f += df;
                            graph[e.t].get(e.rev).f -= df;
                            return df;
                        }
                    }
                }
                return 0;
            }

            long maxFLow(int src, int dest) {
                long flow = 0;
                int[] dist = new int[graph.length];
                while (dinicBFS(src, dest, dist)) {
                    int[] ptr = new int[graph.length];
                    while (true) {
                        long df = dinicDFS(ptr, dist, dest, src, Long.MAX_VALUE);
                        if (df == 0) break;
                        flow += df;
                    }
                }
                return flow;
            }
        }

        int interValIndex;
        public class IntervalNode {
            int l, r;
            IntervalNode left, right;
            int index;
            public IntervalNode(int L, int R) {
                this.l = L;
                this.r = R;
                this.index = interValIndex++;
                int mid = (l + r) / 2;
                if (mid > l) {
                    left = new IntervalNode(l, mid);
                    right = new IntervalNode(mid, r);
                }
            }
        }
        int mfEnd;
        IntervalNode[] baseNodes;
        public void dfsAddEdge(Maxflow mf, IntervalNode node) {
            if (node.left != null) {
                mf.addEdge(node.index, node.left.index, Integer.MAX_VALUE / 2);
                mf.addEdge(node.index, node.right.index, Integer.MAX_VALUE / 2);
                dfsAddEdge(mf, node.left);
                dfsAddEdge(mf, node.right);
            } else {
                baseNodes[node.l] = node;
                mf.addEdge(node.index, mfEnd, 1);
            }
        }

        public void searchCover(Maxflow mf, IntervalNode node, int l, int r, int start) {
            if (l <= node.l && node.r <= r) {
                mf.addEdge(start, node.index, 1);
                return;
            }
            if (node.l >= r || node.r <= l) return;
            searchCover(mf, node.left, l, r, start);
            searchCover(mf, node.right, l, r, start);
        }

        public int dfsDecode(List<Maxflow.Edge>[] graph, int u) {
            for (Maxflow.Edge e: graph[u]) {
                if (e.f > 0) {
                    if (e.t == mfEnd) {
                        e.f -= 1;
                        return u;
                    }
                    int ret = dfsDecode(graph, e.t);
                    if (ret > 0) {
                        e.f -= 1;
                        return ret;
                    }
                }
            }
            return -1;
        }

        public void solve(Scanner sc, PrintWriter pw) throws IOException {
            int n = sc.nextInt();
            int m = sc.nextInt();
            interValIndex = n + 1;
            IntervalNode root = new IntervalNode(0, m);
            mfEnd = interValIndex;
            Maxflow mf = new Maxflow(mfEnd + 1);
            baseNodes = new IntervalNode[m];
            dfsAddEdge(mf, root);
            int[][] weapons = new int[n][];
            for (int i = 0; i < n; i++) {
                int type = sc.nextInt();
                if (type == 0) {
                    int k = sc.nextInt();
                    weapons[i] = new int[k + 1];
                    weapons[i][0] = type;
                    for (int j = 1; j <= k; j++) {
                        weapons[i][j] = sc.nextInt() - 1;
                    }
                    mf.addEdge(0, i + 1, 1);
                    for (int j = 1; j <= k; j++) {
                        mf.addEdge(i + 1, baseNodes[weapons[i][j]].index, 1);
                    }
                } else if (type == 1) {
                    int l = sc.nextInt() - 1;
                    int r = sc.nextInt();
                    weapons[i] = new int[3];
                    weapons[i][0] = type;
                    weapons[i][1] = l;
                    weapons[i][2] = r;
                    mf.addEdge(0, i + 1, 1);
                    searchCover(mf, root, l, r, 1 + i);
                } else if (type == 2) {
                    int a = sc.nextInt() - 1;
                    int b = sc.nextInt() - 1;
                    int c = sc.nextInt() - 1;
                    weapons[i] = new int[4];
                    weapons[i][0] = type;
                    weapons[i][1] = a;
                    weapons[i][2] = b;
                    weapons[i][2] = c;
                    mf.addEdge(0, i + 1, 2);
                    mf.addEdge(i + 1, baseNodes[a].index, 1);
                    mf.addEdge(i + 1, baseNodes[b].index, 1);
                    mf.addEdge(i + 1, baseNodes[c].index, 1);
                }
            }
            long flow = mf.maxFLow(0, mfEnd);
            pw.println(flow);
            List<Maxflow.Edge>[] graph = mf.graph;
            Map<Integer, Integer> toIndex = new HashMap<>();
            for (int i = 0; i < baseNodes.length; i++) {
                toIndex.put(baseNodes[i].index, i);
            }
            toIndex.put(-1, -1);
            int[][] connectTo = new int[n][2];
            for (int i = 0; i < n; i++) {
                connectTo[i][1] = -1;
                connectTo[i][0] = toIndex.get(dfsDecode(graph, i + 1));
                if (weapons[i][0] == 2) connectTo[i][1] = toIndex.get(dfsDecode(graph, i + 1));
            }
            int[] whose = new int[m];
            for (int i = 0; i < n; i++) {
                if (weapons[i][0] != 2 && connectTo[i][0] != -1) {
                    whose[connectTo[i][0]] = i;
                }
            }
            for (int i = 0; i < n; i++) {
                if (weapons[i][0] == 2 && connectTo[i][1] == -1) {
                    for (int j = 1; j < 4; j++) {
                        if (connectTo[i][0] != weapons[i][j]) {
                            connectTo[i][1] = weapons[i][j];
                            connectTo[whose[weapons[i][j]]][0] = -1;
                        }
                    }
                }
            }
            for (int i = 0; i < n; i++) {
                if (connectTo[i][0] >= 0) {
                    pw.println((i + 1) + " " + (connectTo[i][0] + 1));
                }
                if (connectTo[i][1] >= 0) {
                    pw.println((i + 1) + " " + (connectTo[i][1] + 1));
                }
            }
        }
    }

    static long TIME_START, TIME_END;

    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);
//        Scanner sc = new Scanner(new FileInputStream("input"));
        PrintWriter pw = new PrintWriter(new BufferedOutputStream(System.out));
//        PrintWriter pw = new PrintWriter(new FileOutputStream("output"));

        Runtime runtime = Runtime.getRuntime();
        long usedMemoryBefore = runtime.totalMemory() - runtime.freeMemory();
        TIME_START = System.currentTimeMillis();
        Task t = new Task();
        t.solve(sc, pw);
        TIME_END = System.currentTimeMillis();
        long usedMemoryAfter = runtime.totalMemory() - runtime.freeMemory();
        pw.close();
        System.err.println("Memory increased: " + (usedMemoryAfter - usedMemoryBefore) / 1000000);
        System.err.println("Time used: " + (TIME_END - TIME_START) + ".");
    }

    static class Scanner {
        StringTokenizer st;
        BufferedReader br;

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

        public Scanner(FileReader s) throws FileNotFoundException {
            br = new BufferedReader(s);
        }

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

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

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

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

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

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


//package com.company;

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

public class Main {
    public static class Task {

        public class Maxflow {
            class Edge {
                int t, rev;
                long cap, f;
                public Edge(int t, int rev, long cap) {
                    this.t = t;
                    this.rev = rev;
                    this.cap = cap;
                }
            }
            public Maxflow(int n) {
                graph = new List[n];
                for (int i = 0; i < n; i++) {
                    graph[i] = new ArrayList<>();
                }
            }
            List<Edge>[] graph;
            void addEdge(int s, int t, long cap) {
                graph[s].add(new Edge(t, graph[t].size(), cap));
                graph[t].add(new Edge(s, graph[s].size() - 1, 0));
//                if (cap != Integer.MAX_VALUE)
//                System.err.println(s + " " + t + " " + cap);
            }

            boolean dinicBFS(int src, int dest, int[] dist) {
                Arrays.fill(dist, -1);
                dist[src] = 0;
                int[] Q = new int[graph.length];
                int sizeQ = 0;
                Q[sizeQ++] = src;
                for (int i = 0; i < sizeQ; i++) {
                    int u = Q[i];
                    for (Edge e: graph[u]) {
                        if (dist[e.t] < 0 && e.f < e.cap) {
                            dist[e.t] = dist[u] + 1;
                            Q[sizeQ++] = e.t;
                        }
                    }
                }
                return dist[dest] >= 0;
            }

            long dinicDFS(int[] ptr, int[] dist, int dest, int u, long f) {
                if (u == dest) return f;
                for (;ptr[u] < graph[u].size(); ++ptr[u]) {
                    Edge e =  graph[u].get(ptr[u]);
                    if (dist[e.t] == dist[u] + 1 && e.f < e.cap) {
                        long df = dinicDFS(ptr, dist, dest, e.t, Math.min(f, e.cap - e.f));
                        if (df > 0) {
                            e.f += df;
                            graph[e.t].get(e.rev).f -= df;
                            return df;
                        }
                    }
                }
                return 0;
            }

            long maxFLow(int src, int dest) {
                long flow = 0;
                int[] dist = new int[graph.length];
                while (dinicBFS(src, dest, dist)) {
                    int[] ptr = new int[graph.length];
                    while (true) {
                        long df = dinicDFS(ptr, dist, dest, src, Long.MAX_VALUE);
                        if (df == 0) break;
                        flow += df;
                    }
                }
                return flow;
            }
        }

        int interValIndex;
        public class IntervalNode {
            int l, r;
            IntervalNode left, right;
            int index;
            public IntervalNode(int L, int R) {
                this.l = L;
                this.r = R;
                this.index = interValIndex++;
                int mid = (l + r) / 2;
                if (mid > l) {
                    left = new IntervalNode(l, mid);
                    right = new IntervalNode(mid, r);
                }
            }
        }
        int mfEnd;
        IntervalNode[] baseNodes;
        public void dfsAddEdge(Maxflow mf, IntervalNode node) {
            if (node.left != null) {
                mf.addEdge(node.index, node.left.index, Integer.MAX_VALUE / 2);
                mf.addEdge(node.index, node.right.index, Integer.MAX_VALUE / 2);
                dfsAddEdge(mf, node.left);
                dfsAddEdge(mf, node.right);
            } else {
                baseNodes[node.l] = node;
                mf.addEdge(node.index, mfEnd, 1);
            }
        }

        public void searchCover(Maxflow mf, IntervalNode node, int l, int r, int start) {
            if (l <= node.l && node.r <= r) {
                mf.addEdge(start, node.index, 1);
                return;
            }
            if (node.l >= r || node.r <= l) return;
            searchCover(mf, node.left, l, r, start);
            searchCover(mf, node.right, l, r, start);
        }

        public int dfsDecode(List<Maxflow.Edge>[] graph, int u) {
            for (Maxflow.Edge e: graph[u]) {
                if (e.f > 0) {
                    if (e.t == mfEnd) {
                        e.f -= 1;
                        return u;
                    }
                    int ret = dfsDecode(graph, e.t);
                    if (ret > 0) {
                        e.f -= 1;
                        return ret;
                    }
                }
            }
            return -1;
        }

        public void solve(Scanner sc, PrintWriter pw) throws IOException {
            int n = sc.nextInt();
            int m = sc.nextInt();
            interValIndex = n + 1;
            IntervalNode root = new IntervalNode(0, m);
            mfEnd = interValIndex;
            Maxflow mf = new Maxflow(mfEnd + 1);
            baseNodes = new IntervalNode[m];
            dfsAddEdge(mf, root);
            int[][] weapons = new int[n][];
            for (int i = 0; i < n; i++) {
                int type = sc.nextInt();
                if (type == 0) {
                    int k = sc.nextInt();
                    weapons[i] = new int[k + 1];
                    weapons[i][0] = type;
                    for (int j = 1; j <= k; j++) {
                        weapons[i][j] = sc.nextInt() - 1;
                    }
                    mf.addEdge(0, i + 1, 1);
                    for (int j = 1; j <= k; j++) {
                        mf.addEdge(i + 1, baseNodes[weapons[i][j]].index, 1);
                    }
                } else if (type == 1) {
                    int l = sc.nextInt() - 1;
                    int r = sc.nextInt();
                    weapons[i] = new int[3];
                    weapons[i][0] = type;
                    weapons[i][1] = l;
                    weapons[i][2] = r;
                    mf.addEdge(0, i + 1, 1);
                    searchCover(mf, root, l, r, 1 + i);
                } else if (type == 2) {
                    int a = sc.nextInt() - 1;
                    int b = sc.nextInt() - 1;
                    int c = sc.nextInt() - 1;
                    weapons[i] = new int[4];
                    weapons[i][0] = type;
                    weapons[i][1] = a;
                    weapons[i][2] = b;
                    weapons[i][2] = c;
                    mf.addEdge(0, i + 1, 2);
                    mf.addEdge(i + 1, baseNodes[a].index, 1);
                    mf.addEdge(i + 1, baseNodes[b].index, 1);
                    mf.addEdge(i + 1, baseNodes[c].index, 1);
                }
            }
            long flow = mf.maxFLow(0, mfEnd);
            pw.println(flow);
            List<Maxflow.Edge>[] graph = mf.graph;
            Map<Integer, Integer> toIndex = new HashMap<>();
            for (int i = 0; i < baseNodes.length; i++) {
                toIndex.put(baseNodes[i].index, i);
            }
            toIndex.put(-1, -1);
            int[][] connectTo = new int[n][2];
            for (int i = 0; i < n; i++) {
                connectTo[i][1] = -1;
                connectTo[i][0] = toIndex.get(dfsDecode(graph, i + 1));
                if (weapons[i][0] == 2) connectTo[i][1] = toIndex.get(dfsDecode(graph, i + 1));
            }
            int[] whose = new int[m];
            for (int i = 0; i < n; i++) {
                if (weapons[i][0] != 2 && connectTo[i][0] != -1) {
                    whose[connectTo[i][0]] = i;
                }
            }
            for (int i = 0; i < n; i++) {
                if (weapons[i][0] == 2 && connectTo[i][1] == -1) {
                    for (int j = 1; j < 4; j++) {
                        if (connectTo[i][0] != weapons[i][j]) {
                            connectTo[i][1] = weapons[i][j];
                            connectTo[whose[weapons[i][j]]][0] = -1;
                            break;
                        }
                    }
                }
            }
            for (int i = 0; i < n; i++) {
                if (connectTo[i][0] >= 0) {
                    pw.println((i + 1) + " " + (connectTo[i][0] + 1));
                }
                if (connectTo[i][1] >= 0) {
                    pw.println((i + 1) + " " + (connectTo[i][1] + 1));
                }
            }
        }
    }

    static long TIME_START, TIME_END;

    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);
//        Scanner sc = new Scanner(new FileInputStream("input"));
        PrintWriter pw = new PrintWriter(new BufferedOutputStream(System.out));
//        PrintWriter pw = new PrintWriter(new FileOutputStream("output"));

        Runtime runtime = Runtime.getRuntime();
        long usedMemoryBefore = runtime.totalMemory() - runtime.freeMemory();
        TIME_START = System.currentTimeMillis();
        Task t = new Task();
        t.solve(sc, pw);
        TIME_END = System.currentTimeMillis();
        long usedMemoryAfter = runtime.totalMemory() - runtime.freeMemory();
        pw.close();
        System.err.println("Memory increased: " + (usedMemoryAfter - usedMemoryBefore) / 1000000);
        System.err.println("Time used: " + (TIME_END - TIME_START) + ".");
    }

    static class Scanner {
        StringTokenizer st;
        BufferedReader br;

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

        public Scanner(FileReader s) throws FileNotFoundException {
            br = new BufferedReader(s);
        }

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

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

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

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

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

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


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

public class MadokaAndTheBestUniversity {
	private static final int N_MAX = 100_000;

	private static final int MOD = 1_000_000_007;

	private static final IntList[] FACTORS = new IntList[N_MAX + 1];
	static {
		for (int i = 1; i <= N_MAX; ++i) {
			FACTORS[i] = new IntList();
		}
		for (int i = 1; i <= N_MAX; ++i) {
			for (int j = i; j <= N_MAX; j += i) {
				FACTORS[j].add(i);
			}
		}
	}

	private static final int[] TOTIENT = new int[N_MAX + 1];
	static {
		for (int i = 1; i < TOTIENT.length; ++i) {
			TOTIENT[i] = i;
		}
		for (int i = 2; i < TOTIENT.length; ++i) {
			if (TOTIENT[i] != i) {
				continue;
			}
			for (int j = i; j < TOTIENT.length; j += i) {
				TOTIENT[j] -= TOTIENT[j] / i;
			}
		}
	}

	public static void solve(FastIO io) {
		final int N = io.nextInt();

		long total = 0;
		for (int c = 1; c + 2 <= N; ++c) {
			int rem = N - c;
			IntList facs = FACTORS[rem];
			for (int i = facs.size() - 2; i >= 0; --i) {
				int fi = facs.get(i);
				total += 1L * lcm(c, fi) * TOTIENT[rem / fi];
				total %= MOD;
			}
		}
		io.println(total);
	}

	/**
	 * Computes the GCD (greatest common denominator) between two numbers.
	 */
	public static int gcd(int a, int b) {
		if (a < b)
			return gcd(b, a);

		int r = a % b;
		if (r == 0)
			return b;

		return gcd(b, r);
	}

	/**
	 * Computes the LCM (least common multiple) between all the numbers.
	 */
	public static int lcm(int... arr) {
		int lcm = arr[0];
		for (int i = 1; i < arr.length; i++)
			lcm = lcm * arr[i] / gcd(lcm, arr[i]);

		return lcm;
	}

	private static class IntList extends ArrayList<Integer> {
		private static final long serialVersionUID = 8986468115134862220L;
	}

	public static class FastIO {
		private InputStream reader;
		private PrintWriter writer;

		private byte[] buf = new byte[1024];
		private int curChar;
		private int numChars;

		public FastIO(InputStream r, OutputStream w) {
			reader = r;
			writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(w)));
		}

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

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

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

		public long nextLong() {
			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 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;
		}

		// TODO: read this byte-by-byte like the other read functions.
		public double nextDouble() {
			return Double.parseDouble(nextString());
		}

		public int[] nextIntArray(int n) {
			return nextIntArray(n, 0);
		}

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

		public long[] nextLongArray(int n) {
			return nextLongArray(n, 0);
		}

		public long[] nextLongArray(int n, int off) {
			long[] arr = new long[n + off];
			for (int i = 0; i < n; i++) {
				arr[i + off] = nextLong();
			}
			return arr;
		}

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

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

		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 printArray(int[] arr) {
			for (int i = 0; i < arr.length; i++) {
				if (i != 0) {
					writer.print(' ');
				}
				writer.print(arr[i]);
			}
		}

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

		public void printlnArray(int[] arr) {
			printArray(arr);
			writer.println();
		}

		public void printlnArray(long[] arr) {
			printArray(arr);
			writer.println();
		}

		public void printf(String format, Object... args) {
			print(String.format(format, args));
		}

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

	public static void main(String[] args) {
		FastIO io = new FastIO(System.in, System.out);
		solve(io);
		io.flush();
	}
}


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

public class Main {
    static ContestScanner sc = new ContestScanner(System.in);
    static PrintWriter pw = new PrintWriter(System.out);
    static StringBuilder sb = new StringBuilder();
    static long mod = (long) 1e9 + 7;

    public static void main(String[] args) throws Exception {
        //int T = sc.nextInt();
        //for(int i = 0; i < T; i++)solve();
        solve();
        pw.flush();
    }

    public static void solve() {
        int n = sc.nextInt();
        Sieve s = new Sieve(n+1);
        HashMap<Integer,Long> modMap = new HashMap<>();
        for(int i = 2; i <= n; i++){
            modMap.put(i,extGCD.modinv(i,mod));
        }
        long ans = 0;
        for(int c = 1; c <= n-2; c++){
            HashSet<Integer> arr = new HashSet<>();
            arr.add(1);
            int r = n-c;
            int max = (int)Math.sqrt(r)+1;
            for(int j = 2; j <= max; j++){
                if(r % j == 0){
                    arr.add(r/j);
                    arr.add(j);
                }
            }
            for(int d : arr){
                HashMap<Integer,Integer> map = s.factor((n-c)/d);
                long tmp = (n-c)/d;
                for(Map.Entry<Integer,Integer> e : map.entrySet()){
                    int k = e.getKey();
                    tmp *= modMap.get(k);
                    tmp %= mod;
                    tmp *= (k-1);
                    tmp %= mod;
                }
                ans += (lcm(c,d)*tmp)%mod;
                ans %= mod;
            }
        }
        pw.println(ans);
    }

    private static long gcd(long a, long b)
    {
        while (b > 0)
        {
            long temp = b;
            b = a % b; // % is remainder
            a = temp;
        }
        return a;
    }

    private static long lcm(long a, long b)
    {
        return a * (b / gcd(a, b));
    }

    static class GeekInteger {
        public static void save_sort(int[] array) {
            shuffle(array);
            Arrays.sort(array);
        }

        public static int[] shuffle(int[] array) {
            int n = array.length;
            Random random = new Random();
            for (int i = 0, j; i < n; i++) {
                j = i + random.nextInt(n - i);
                int randomElement = array[j];
                array[j] = array[i];
                array[i] = randomElement;
            }
            return array;
        }

        public static void save_sort(long[] array) {
            shuffle(array);
            Arrays.sort(array);
        }

        public static long[] shuffle(long[] array) {
            int n = array.length;
            Random random = new Random();
            for (int i = 0, j; i < n; i++) {
                j = i + random.nextInt(n - i);
                long randomElement = array[j];
                array[j] = array[i];
                array[i] = randomElement;
            }
            return array;
        }

    }
}

class extGCD {
    static long[] extGCD(long a, long b) {
        long x = 1, y = 0, u = 0, v = 1, s = a, t = b;
        long k = 0, tmp = 0;
        while (t > 0) {
            k = s / t;
            s -= k * t;
            {
                tmp = s;
                s = t;
                t = tmp;
            }
            x -= k * u;
            {
                tmp = x;
                x = u;
                u = tmp;
            }
            y -= k * v;
            {
                tmp = y;
                y = v;
                v = tmp;
            }
        }
        return new long[] { x, y };
    }

    static long modinv(long a, long mod) {
        long x = 1, u = 0, s = a, t = mod;
        long k = 0, tmp = 0;
        while (t > 0) {
            k = s / t;
            s -= k * t;
            {
                tmp = s;
                s = t;
                t = tmp;
            }
            x -= k * u;
            {
                tmp = x;
                x = u;
                u = tmp;
            }
        }
        x %= mod;
        if (x < 0)
            x += mod;
        return x;
    }
}

class Sieve{
    static int n;
    static int[] f;
    static ArrayList<Integer> prime;
    public Sieve(int n){
        long ln = n;
        prime = new ArrayList<Integer>();
        f = new int[n+1];
        f[0] = f[1] = -1;
        for(int i = 2; i <= n; i++){
            if(f[i] != 0){
                continue;
            }
            f[i] = i;
            prime.add(i);
            long li = (long)i;
            for(long j = li*li; j <= ln; j += li){
                if(f[(int)j] == 0){
                    f[(int)j] = i;
                }
            }
        }
    }

    public static boolean isPrime(int x){
        return f[x] == x;
    }

    public static ArrayList<Integer> factorList(int x){
        ArrayList<Integer> res = new ArrayList<Integer>();
        while(x != 1){
            res.add(f[x]);
            x /= f[x];
        }
        return res;
    }

    public static HashMap<Integer,Integer> factor(int x){
        ArrayList<Integer> fl = factorList(x);
        HashMap<Integer,Integer> res = new HashMap<Integer,Integer>();
        if(fl.size()==0){
            return new HashMap<Integer,Integer>();
        }
        int prev = fl.get(0);
        int cnt = 0;
        for(int p : fl){
            if(prev == p){
                cnt++;
            }else{
                res.put(prev,cnt);
                prev = p;
                cnt = 1;
            }
        }
        res.put(prev,cnt);
        return res;
    }
}

/**
 * refercence : https://github.com/NASU41/AtCoderLibraryForJava/blob/master/ContestIO/ContestScanner.java
 */
class ContestScanner {
    private final java.io.InputStream in;
    private final byte[] buffer = new byte[1024];
    private int ptr = 0;
    private int buflen = 0;

    private static final long LONG_MAX_TENTHS = 922337203685477580L;
    private static final int LONG_MAX_LAST_DIGIT = 7;
    private static final int LONG_MIN_LAST_DIGIT = 8;

    public ContestScanner(java.io.InputStream in){
        this.in = in;
    }
    public ContestScanner(java.io.File file) throws java.io.FileNotFoundException {
        this(new java.io.BufferedInputStream(new java.io.FileInputStream(file)));
    }
    public ContestScanner(){
        this(System.in);
    }

    private boolean hasNextByte() {
        if (ptr < buflen) {
            return true;
        }else{
            ptr = 0;
            try {
                buflen = in.read(buffer);
            } catch (java.io.IOException e) {
                e.printStackTrace();
            }
            if (buflen <= 0) {
                return false;
            }
        }
        return true;
    }
    private int readByte() {
        if (hasNextByte()) return buffer[ptr++]; else return -1;
    }
    private static boolean isPrintableChar(int c) {
        return 33 <= c && c <= 126;
    }
    public boolean hasNext() {
        while(hasNextByte() && !isPrintableChar(buffer[ptr])) ptr++;
        return hasNextByte();
    }
    public String next() {
        if (!hasNext()) throw new java.util.NoSuchElementException();
        StringBuilder sb = new StringBuilder();
        int b = readByte();
        while(isPrintableChar(b)) {
            sb.appendCodePoint(b);
            b = readByte();
        }
        return sb.toString();
    }

    public long nextLong() {
        if (!hasNext()) throw new java.util.NoSuchElementException();
        long n = 0;
        boolean minus = false;
        int b = readByte();
        if (b == '-') {
            minus = true;
            b = readByte();
        }
        if (b < '0' || '9' < b) {
            throw new NumberFormatException();
        }
        while (true) {
            if ('0' <= b && b <= '9') {
                int digit = b - '0';
                if (n >= LONG_MAX_TENTHS) {
                    if (n == LONG_MAX_TENTHS) {
                        if (minus) {
                            if (digit <= LONG_MIN_LAST_DIGIT) {
                                n = -n * 10 - digit;
                                b = readByte();
                                if (!isPrintableChar(b)) {
                                    return n;
                                } else if (b < '0' || '9' < b) {
                                    throw new NumberFormatException(
                                        String.format("%d%s... is not number", n, Character.toString(b))
                                    );
                                }
                            }
                        } else {
                            if (digit <= LONG_MAX_LAST_DIGIT) {
                                n = n * 10 + digit;
                                b = readByte();
                                if (!isPrintableChar(b)) {
                                    return n;
                                } else if (b < '0' || '9' < b) {
                                    throw new NumberFormatException(
                                        String.format("%d%s... is not number", n, Character.toString(b))
                                    );
                                }
                            }
                        }
                    }
                    throw new ArithmeticException(
                        String.format("%s%d%d... overflows long.", minus ? "-" : "", n, digit)
                    );
                }
                n = n * 10 + digit;
            }else if(b == -1 || !isPrintableChar(b)){
                return minus ? -n : n;
            }else{
                throw new NumberFormatException();
            }
            b = readByte();
        }
    }
    public int nextInt() {
        long nl = nextLong();
        if (nl < Integer.MIN_VALUE || nl > Integer.MAX_VALUE) throw new NumberFormatException();
        return (int) nl;
    }
    public double nextDouble() {
        return Double.parseDouble(next());
    }

    public long[] nextLongArray(int length){
        long[] array = new long[length];
        for(int i=0; i<length; i++) array[i] = this.nextLong();
        return array;
    }
    public long[] nextLongArray(int length, java.util.function.LongUnaryOperator map){
        long[] array = new long[length];
        for(int i=0; i<length; i++) array[i] = map.applyAsLong(this.nextLong());
        return array;
    }
    public int[] nextIntArray(int length){
        int[] array = new int[length];
        for(int i=0; i<length; i++) array[i] = this.nextInt();
        return array;
    }
    public int[] nextIntArray(int length, java.util.function.IntUnaryOperator map){
        int[] array = new int[length];
        for(int i=0; i<length; i++) array[i] = map.applyAsInt(this.nextInt());
        return array;
    }
    public double[] nextDoubleArray(int length){
        double[] array = new double[length];
        for(int i=0; i<length; i++) array[i] = this.nextDouble();
        return array;
    }
    public double[] nextDoubleArray(int length, java.util.function.DoubleUnaryOperator map){
        double[] array = new double[length];
        for(int i=0; i<length; i++) array[i] = map.applyAsDouble(this.nextDouble());
        return array;
    }

    public long[][] nextLongMatrix(int height, int width){
        long[][] mat = new long[height][width];
        for(int h=0; h<height; h++) for(int w=0; w<width; w++){
            mat[h][w] = this.nextLong();
        }
        return mat;
    }
    public int[][] nextIntMatrix(int height, int width){
        int[][] mat = new int[height][width];
        for(int h=0; h<height; h++) for(int w=0; w<width; w++){
            mat[h][w] = this.nextInt();
        }
        return mat;
    }
    public double[][] nextDoubleMatrix(int height, int width){
        double[][] mat = new double[height][width];
        for(int h=0; h<height; h++) for(int w=0; w<width; w++){
            mat[h][w] = this.nextDouble();
        }
        return mat;
    }

    public char[][] nextCharMatrix(int height, int width){
        char[][] mat = new char[height][width];
        for(int h=0; h<height; h++){
            String s = this.next();
            for(int w=0; w<width; w++){
                mat[h][w] = s.charAt(w);
            }
        }
        return mat;
    }
}


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

public class Main {
    static ContestScanner sc = new ContestScanner(System.in);
    static PrintWriter pw = new PrintWriter(System.out);
    static StringBuilder sb = new StringBuilder();
    static long mod = (long) 1e9 + 7;

    public static void main(String[] args) throws Exception {
        //int T = sc.nextInt();
        //for(int i = 0; i < T; i++)solve();
        solve();
        pw.flush();
    }

    public static void solve() {
        int n = sc.nextInt();
        Sieve s = new Sieve(n+1);
        HashMap<Integer,Long> modMap = new HashMap<>();
        for(int i = 2; i <= n; i++){
            modMap.put(i,extGCD.modinv(i,mod));
        }
        long ans = 0;
        for(int c = 1; c <= n-2; c++){
            HashSet<Integer> arr = new HashSet<>();
            int r = n-c;
            int max = (int)Math.sqrt(r)+1;
            for(int j = 1; j <= max; j++){
                if(r % j == 0){
                    arr.add(r/j);
                    arr.add(j);
                }
            }
            for(int d : arr){
                if(d == n-c) continue;
                HashMap<Integer,Integer> map = s.factor((n-c)/d);
                long tmp = (n-c)/d;
                for(Map.Entry<Integer,Integer> e : map.entrySet()){
                    int k = e.getKey();
                    tmp *= (k-1)*modMap.get(k);
                    tmp %= mod;
                }
                ans += (lcm(c,d)*tmp)%mod;
                ans %= mod;
            }
        }
        pw.println(ans);
    }

    private static long gcd(long a, long b)
    {
        while (b > 0)
        {
            long temp = b;
            b = a % b; // % is remainder
            a = temp;
        }
        return a;
    }

    private static long lcm(long a, long b)
    {
        return a * (b / gcd(a, b));
    }

    static class GeekInteger {
        public static void save_sort(int[] array) {
            shuffle(array);
            Arrays.sort(array);
        }

        public static int[] shuffle(int[] array) {
            int n = array.length;
            Random random = new Random();
            for (int i = 0, j; i < n; i++) {
                j = i + random.nextInt(n - i);
                int randomElement = array[j];
                array[j] = array[i];
                array[i] = randomElement;
            }
            return array;
        }

        public static void save_sort(long[] array) {
            shuffle(array);
            Arrays.sort(array);
        }

        public static long[] shuffle(long[] array) {
            int n = array.length;
            Random random = new Random();
            for (int i = 0, j; i < n; i++) {
                j = i + random.nextInt(n - i);
                long randomElement = array[j];
                array[j] = array[i];
                array[i] = randomElement;
            }
            return array;
        }

    }
}

class extGCD {
    static long[] extGCD(long a, long b) {
        long x = 1, y = 0, u = 0, v = 1, s = a, t = b;
        long k = 0, tmp = 0;
        while (t > 0) {
            k = s / t;
            s -= k * t;
            {
                tmp = s;
                s = t;
                t = tmp;
            }
            x -= k * u;
            {
                tmp = x;
                x = u;
                u = tmp;
            }
            y -= k * v;
            {
                tmp = y;
                y = v;
                v = tmp;
            }
        }
        return new long[] { x, y };
    }

    static long modinv(long a, long mod) {
        long x = 1, u = 0, s = a, t = mod;
        long k = 0, tmp = 0;
        while (t > 0) {
            k = s / t;
            s -= k * t;
            {
                tmp = s;
                s = t;
                t = tmp;
            }
            x -= k * u;
            {
                tmp = x;
                x = u;
                u = tmp;
            }
        }
        x %= mod;
        if (x < 0)
            x += mod;
        return x;
    }
}

class Sieve{
    static int n;
    static int[] f;
    static ArrayList<Integer> prime;
    public Sieve(int n){
        long ln = n;
        prime = new ArrayList<Integer>();
        f = new int[n+1];
        f[0] = f[1] = -1;
        for(int i = 2; i <= n; i++){
            if(f[i] != 0){
                continue;
            }
            f[i] = i;
            prime.add(i);
            long li = (long)i;
            for(long j = li*li; j <= ln; j += li){
                if(f[(int)j] == 0){
                    f[(int)j] = i;
                }
            }
        }
    }

    public static boolean isPrime(int x){
        return f[x] == x;
    }

    public static ArrayList<Integer> factorList(int x){
        ArrayList<Integer> res = new ArrayList<Integer>();
        while(x != 1){
            res.add(f[x]);
            x /= f[x];
        }
        return res;
    }

    public static HashMap<Integer,Integer> factor(int x){
        ArrayList<Integer> fl = factorList(x);
        HashMap<Integer,Integer> res = new HashMap<Integer,Integer>();
        if(fl.size()==0){
            return new HashMap<Integer,Integer>();
        }
        int prev = fl.get(0);
        int cnt = 0;
        for(int p : fl){
            if(prev == p){
                cnt++;
            }else{
                res.put(prev,cnt);
                prev = p;
                cnt = 1;
            }
        }
        res.put(prev,cnt);
        return res;
    }
}

/**
 * refercence : https://github.com/NASU41/AtCoderLibraryForJava/blob/master/ContestIO/ContestScanner.java
 */
class ContestScanner {
    private final java.io.InputStream in;
    private final byte[] buffer = new byte[1024];
    private int ptr = 0;
    private int buflen = 0;

    private static final long LONG_MAX_TENTHS = 922337203685477580L;
    private static final int LONG_MAX_LAST_DIGIT = 7;
    private static final int LONG_MIN_LAST_DIGIT = 8;

    public ContestScanner(java.io.InputStream in){
        this.in = in;
    }
    public ContestScanner(java.io.File file) throws java.io.FileNotFoundException {
        this(new java.io.BufferedInputStream(new java.io.FileInputStream(file)));
    }
    public ContestScanner(){
        this(System.in);
    }

    private boolean hasNextByte() {
        if (ptr < buflen) {
            return true;
        }else{
            ptr = 0;
            try {
                buflen = in.read(buffer);
            } catch (java.io.IOException e) {
                e.printStackTrace();
            }
            if (buflen <= 0) {
                return false;
            }
        }
        return true;
    }
    private int readByte() {
        if (hasNextByte()) return buffer[ptr++]; else return -1;
    }
    private static boolean isPrintableChar(int c) {
        return 33 <= c && c <= 126;
    }
    public boolean hasNext() {
        while(hasNextByte() && !isPrintableChar(buffer[ptr])) ptr++;
        return hasNextByte();
    }
    public String next() {
        if (!hasNext()) throw new java.util.NoSuchElementException();
        StringBuilder sb = new StringBuilder();
        int b = readByte();
        while(isPrintableChar(b)) {
            sb.appendCodePoint(b);
            b = readByte();
        }
        return sb.toString();
    }

    public long nextLong() {
        if (!hasNext()) throw new java.util.NoSuchElementException();
        long n = 0;
        boolean minus = false;
        int b = readByte();
        if (b == '-') {
            minus = true;
            b = readByte();
        }
        if (b < '0' || '9' < b) {
            throw new NumberFormatException();
        }
        while (true) {
            if ('0' <= b && b <= '9') {
                int digit = b - '0';
                if (n >= LONG_MAX_TENTHS) {
                    if (n == LONG_MAX_TENTHS) {
                        if (minus) {
                            if (digit <= LONG_MIN_LAST_DIGIT) {
                                n = -n * 10 - digit;
                                b = readByte();
                                if (!isPrintableChar(b)) {
                                    return n;
                                } else if (b < '0' || '9' < b) {
                                    throw new NumberFormatException(
                                        String.format("%d%s... is not number", n, Character.toString(b))
                                    );
                                }
                            }
                        } else {
                            if (digit <= LONG_MAX_LAST_DIGIT) {
                                n = n * 10 + digit;
                                b = readByte();
                                if (!isPrintableChar(b)) {
                                    return n;
                                } else if (b < '0' || '9' < b) {
                                    throw new NumberFormatException(
                                        String.format("%d%s... is not number", n, Character.toString(b))
                                    );
                                }
                            }
                        }
                    }
                    throw new ArithmeticException(
                        String.format("%s%d%d... overflows long.", minus ? "-" : "", n, digit)
                    );
                }
                n = n * 10 + digit;
            }else if(b == -1 || !isPrintableChar(b)){
                return minus ? -n : n;
            }else{
                throw new NumberFormatException();
            }
            b = readByte();
        }
    }
    public int nextInt() {
        long nl = nextLong();
        if (nl < Integer.MIN_VALUE || nl > Integer.MAX_VALUE) throw new NumberFormatException();
        return (int) nl;
    }
    public double nextDouble() {
        return Double.parseDouble(next());
    }

    public long[] nextLongArray(int length){
        long[] array = new long[length];
        for(int i=0; i<length; i++) array[i] = this.nextLong();
        return array;
    }
    public long[] nextLongArray(int length, java.util.function.LongUnaryOperator map){
        long[] array = new long[length];
        for(int i=0; i<length; i++) array[i] = map.applyAsLong(this.nextLong());
        return array;
    }
    public int[] nextIntArray(int length){
        int[] array = new int[length];
        for(int i=0; i<length; i++) array[i] = this.nextInt();
        return array;
    }
    public int[] nextIntArray(int length, java.util.function.IntUnaryOperator map){
        int[] array = new int[length];
        for(int i=0; i<length; i++) array[i] = map.applyAsInt(this.nextInt());
        return array;
    }
    public double[] nextDoubleArray(int length){
        double[] array = new double[length];
        for(int i=0; i<length; i++) array[i] = this.nextDouble();
        return array;
    }
    public double[] nextDoubleArray(int length, java.util.function.DoubleUnaryOperator map){
        double[] array = new double[length];
        for(int i=0; i<length; i++) array[i] = map.applyAsDouble(this.nextDouble());
        return array;
    }

    public long[][] nextLongMatrix(int height, int width){
        long[][] mat = new long[height][width];
        for(int h=0; h<height; h++) for(int w=0; w<width; w++){
            mat[h][w] = this.nextLong();
        }
        return mat;
    }
    public int[][] nextIntMatrix(int height, int width){
        int[][] mat = new int[height][width];
        for(int h=0; h<height; h++) for(int w=0; w<width; w++){
            mat[h][w] = this.nextInt();
        }
        return mat;
    }
    public double[][] nextDoubleMatrix(int height, int width){
        double[][] mat = new double[height][width];
        for(int h=0; h<height; h++) for(int w=0; w<width; w++){
            mat[h][w] = this.nextDouble();
        }
        return mat;
    }

    public char[][] nextCharMatrix(int height, int width){
        char[][] mat = new char[height][width];
        for(int h=0; h<height; h++){
            String s = this.next();
            for(int w=0; w<width; w++){
                mat[h][w] = s.charAt(w);
            }
        }
        return mat;
    }
}


/* package codechef; // don't place package name! */

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 Codechef
{
    static class Reader {
        final private int BUFFER_SIZE = 1 << 16;
        private DataInputStream din;
        private byte[] buffer;
        private int bufferPointer, bytesRead;

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

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

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

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

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

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

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

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

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

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

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

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

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

    public static long gcd(long a, long b)
    {
        if (a == 0)
            return b;

        return gcd(b % a, a);
    }

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

           Reader sc = new Reader();
           int n = sc.nextInt();

        long phi[] = new long[n + 1];
    for (int i = 1; i <= n; i++)
    phi[i] = i; // indicates not evaluated yet
                // and initializes for product
                // formula.

    // Compute other Phi values
    for (int p = 2; p <= n; p++) {

    // If phi[p] is not computed already,
    // then number p is prime
    if (phi[p] == p) {

        // Phi of a prime number p is
        // always equal to p-1.
        phi[p] = p - 1;

        // Update phi values of all
        // multiples of p
        for (int i = 2 * p; i <= n; i += p) {

        // Add contribution of p to its
        // multiple i by multiplying with
        // (1 - 1/p)
        phi[i] = (phi[i] / p) * (p - 1);
        }
    }
    }

    long ans = 0;
    long mod = 1000000007;
           for(int c = 1 ; c <= n-2 ; c++)
           {
               int sum = n-c;
               for(int j = 1 ; j <= (int)Math.sqrt(sum) ; j++)
               {
                   if(sum%j == 0)
                   {
                       int xx = sum/j;
                       long lc = (long)c*(long)j/(gcd(c,j));

                       ans += lc*phi[xx]%mod;
                       ans %= mod;
                   }
               }
           }
           System.out.println(ans);
    }
}


import java.util.Scanner;

public class B {
    public static void main(String[] args) {
        Scanner s = new Scanner(System.in);
        int x = s.nextInt()L
        System.out.println(2 - (x * x));
    }
}


import java.util.*;
public class math {
    public static void main(String args[]);
    Scanner sc = new Scanner(System.in);
    int n = sc.nextInt();
    System.out.println((int)Math.pow(n , 2) - (2 * n));
}


import java.util.*;
public class math {
    public static void main(String args[]);
    Scanner sc = new Scanner(System.in);
    int n = sc.nextInt();
    System.out.println(2 - n * n);
}


import java.util.*;
public class math {
    public static void main(String args[]);
    Scanner sc = new Scanner(System.in);
    int n = sc.nextInt();
    System.out.println(2-n*n);
}


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

public class Main{
	public static void main(String args[]) throws IOException{
		new Main().mains();
	}
	public int m,n,H[],tot[],ans,x[],y[],tim[];

	void push(int a, int b){
		x[++ ans] = a;
		y[ans] = b;
	}

	void easy_move(int a, int b, int c, int bottom){
		if (bottom == n + 1) return;
		easy_move(a, c, b, bottom + 1);
		for (int i = 1; i <= tot[bottom]; i ++)
			push(a, c);
		easy_move(b, a, c, bottom + 1);
	}

	void solve(int a, int b, int c, int bottom, boolean flag){
		if (bottom == n + 1) return;
		if (tot[bottom] == 1){
			easy_move(a, c, b, bottom + 1);
			push(a, c);
			solve(b, a, c, bottom + 1, true);
			return;
		}
		if (flag == true){
			easy_move(a, c, b, bottom + 1);
			for (int i = 1; i <= tot[bottom]; i ++)
				push(a, c);
			solve(b, a, c, bottom + 1, true);
		} else {
			if (bottom == n){
				for (int i = 1; i <= tot[bottom] - 1; i ++)
					push(a, b);
				push(a, c);
				for (int i = 1; i <= tot[bottom] - 1; i ++)
					push(b, c);
			} else {
				easy_move(a, b, c, bottom + 1);
				for (int i = 1; i <= tot[bottom]; i ++)
					push(a, b);
				easy_move(c, b, a, bottom + 1);
				for (int i = 1; i <= tot[bottom]; i ++)
					push(b, c);
				solve(a, b, c, bottom + 1, false);
			}
		}
	}

	public void solve() throws IOException{
		m = nextInt();
		H = new int[100];
		tot = new int[100];
		x = new int[1000000];
		tim = new int[100];
		y = new int[1000000];
		for (int i = 1; i <= m; i ++){
			int k = nextInt();
			if (k != H[n]){
				H[++ n] = k;
			}
			tot[n] ++;
		}
		for (int i = n; i > 0; i --)
			tim[i] = tim[i + 1] * 2 + tot[i];
		solve(1, 2, 3, 1, false);
		out.println(ans);
		for (int i = 1; i <= ans; i ++)
			out.println(x[i] + " " + y[i]);
	}

	void mains() throws IOException{
		reader = new BufferedReader(new InputStreamReader(System.in));
		out = new PrintWriter(new OutputStreamWriter(System.out));
		tokenizer = null;
		//File fin = new File("a.in");
		//reader = new BufferedReader(new InputStreamReader(new FileInputStream(fin)));
		//out = new PrintWriter("a.out");
		solve();
		reader.close();
		out.flush();
	}

	BufferedReader reader;
	StringTokenizer tokenizer;
	PrintWriter out;
	int nextInt() throws IOException {
		return Integer.parseInt(nextToken());
	}
	long nextLong() throws IOException {
		return Long.parseLong(nextToken());
	}
	double nextDouble() throws IOException {
		return Double.parseDouble(nextToken());
	}
	String nextToken() throws IOException {
		while (tokenizer == null || !tokenizer.hasMoreTokens()) {
			tokenizer = new StringTokenizer(reader.readLine());
		}
		return tokenizer.nextToken();
	}

}


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

public class Main{
	public static void main(String args[]) throws IOException{
		new Main().mains();
	}
	public int m,n,H[],tot[],ans,x[],y[];

	void push(int a, int b){
		x[++ ans] = a;
		y[ans] = b;
	}

	void easy_move(int a, int b, int c, int bottom){
		if (bottom == n + 1) return;
		easy_move(a, c, b, bottom + 1);
		for (int i = 1; i <= tot[bottom]; i ++)
			push(a, c);
		easy_move(b, a, c, bottom + 1);
	}

	void solve(int a, int b, int c, int bottom, boolean flag){
		if (bottom == n + 1) return;
		if (tot[bottom] == 1){
			easy_move(a, c, b, bottom + 1);
			push(a, c);
			solve(b, a, c, bottom + 1, true);
			return;
		}
		if (flag == true){
			easy_move(a, c, b, bottom + 1);
			for (int i = 1; i <= tot[bottom]; i ++)
				push(a, c);
			solve(b, a, c, bottom + 1, true);
		} else {
			easy_move(a, b, c, bottom + 1);
			for (int i = 1; i <= tot[bottom] - 1; i ++)
				push(a, b);
			easy_move(c, a, b, bottom + 1);
			push(a, c);
			easy_move(b, c, a, bottom + 1);
			for (int i = 1; i <= tot[bottom] - 1; i ++)
				push(b, c);
			solve(a, b, c, bottom + 1, true);
		}
	}

	public void solve() throws IOException{
		m = nextInt();
		H = new int[100];
		tot = new int[100];
		x = new int[1000000];
		y = new int[1000000];
		for (int i = 1; i <= m; i ++){
			int k = nextInt();
			if (k != H[n]){
				H[++ n] = k;
			}
			tot[n] ++;
		}
		solve(1, 2, 3, 1, false);
		out.println(ans);
		for (int i = 1; i <= ans; i ++)
			out.println(x[i] + " " + y[i]);
	}

	void mains() throws IOException{
		//reader = new BufferedReader(new InputStreamReader(System.in));
		//out = new PrintWriter(new OutputStreamWriter(System.out));
		tokenizer = null;
		File fin = new File("a.in");
		reader = new BufferedReader(new InputStreamReader(new FileInputStream(fin)));
		out = new PrintWriter("a.out");
		solve();
		reader.close();
		out.flush();
	}

	BufferedReader reader;
	StringTokenizer tokenizer;
	PrintWriter out;
	int nextInt() throws IOException {
		return Integer.parseInt(nextToken());
	}
	long nextLong() throws IOException {
		return Long.parseLong(nextToken());
	}
	double nextDouble() throws IOException {
		return Double.parseDouble(nextToken());
	}
	String nextToken() throws IOException {
		while (tokenizer == null || !tokenizer.hasMoreTokens()) {
			tokenizer = new StringTokenizer(reader.readLine());
		}
		return tokenizer.nextToken();
	}

}


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

public class Main
{
	public BufferedReader in;
	public PrintStream out;

	int[] disks;
	int K;

	public long calc(int from, boolean keep_order)
	{
		if (from==K)
		{
			return keep_order ? 2*disks[K]-1 : disks[K];
		}

		if (disks[from]==1)
		{
			return 1+2*calc(from+1, false);
		}

		return keep_order
			? 2*calc(from+1, false) + calc(from+1, true) + 2*disks[from]
			: 2*calc(from+1, false) + disks[from]  ;
	}

	public void print_move(int from, int to, int k)
	{
		for (int i=0; i<k; i++)
		{
			out.print(from);
			out.print(" ");
			out.println(to);
		}
	}

	public void print(int from, boolean keep_order, int sourse, int dest, int buf)
	{
		int k = disks[from];
		if (from==K)
		{
			if (keep_order)
			{
				print_move(sourse, buf, k-1);
				print_move(sourse, dest, 1);
				print_move(buf, dest, k-1);
			}
			else
			{
				print_move(sourse, dest, k);
			}
		}
		else
		{
			if ((k==1) || !keep_order)
			{
				print(from+1, false, sourse, buf, dest);
				print_move(sourse, dest, k);
				print(from+1, false, buf, dest, sourse);
			}
			else
			{
				print(from+1, false, sourse, dest, buf);
				print_move(sourse, buf, k);
				print(from+1, false, dest, sourse, buf);
				print_move(buf, dest, k);
				print(from+1, true, sourse, dest, buf);
			}
		}
	}

	public void test()
	{
		int n = readInt();
		int[] d = readIntArray(n);

		int i, prev = 0;

		K = -1;
		disks = new int[n];

		for (i=0; i<n; i++)
		{
			if (d[i]==prev)
			{
				disks[K]++;
			}
			else
			{
				disks[++K] = 1;
			}

			prev = d[i];
		}

		long count = calc(0, true);

		out.println(count);

		print(0, true, 1,3,2);
	}

	public void run()
	{
		try
		{
			in = new BufferedReader(new InputStreamReader(System.in));
			out = System.out;

			//in = new BufferedReader(new FileReader("in.txt"));
			//out = new PrintStream(new File("out.txt"));

		}
		catch (Exception e)
		{
			return;
		}

		//int t = readInt(); for (int i=0; i<t; i++)
		{
			test();
		}
	}

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

	private StringTokenizer tokenizer = null;

	public int readInt()
	{
        return Integer.parseInt(readToken());
    }

    public long readLong()
	{
        return Long.parseLong(readToken());
    }

    public double readDouble()
	{
        return Double.parseDouble(readToken());
    }

	public String readLn()
	{
		try
		{
			String s;
			while ((s = in.readLine()).length()==0);
			return s;
		}
		catch (Exception e)
		{
			return "";
		}
	}

    public String readToken()
	{
		try
		{
			while (tokenizer == null || !tokenizer.hasMoreTokens())
			{
				tokenizer = new StringTokenizer(in.readLine());
			}
			return tokenizer.nextToken();
		}
		catch (Exception e)
		{
			return "";
		}
    }

	public int[] readIntArray(int n)
	{
		int[] x = new int[n];
		readIntArray(x, n);
		return x;
	}

	public void readIntArray(int[] x, int n)
	{
		for (int i=0; i<n; i++)
		{
			x[i] = readInt();
		}
	}
}


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

public class Solution {
    InputStreamReader inp = new InputStreamReader(System.in);
    BufferedReader br = new BufferedReader(inp);
    Scanner sc = new Scanner(inp);

    class Peg {
        int cnt;
        int[] data = new int[30];

        public Peg() {
            cnt = 0;
        }

        public void put(int x) {
            data[cnt++] = x;
        }

        public int take() {
            return data[--cnt];
        }
    }

    // input data

    Peg[] pegs = new Peg[4];

    void inputData() {
        for (int i=1; i<=3; i++)
            pegs[i] = new Peg();

        int n = sc.nextInt();
        for (int i=0; i < n; i++) {
            int d = sc.nextInt();
            pegs[1].put(d);
        }
    }

    // intermediate

    List<Integer> a = new ArrayList<Integer>();
    List<Integer> b = new ArrayList<Integer>();

    void move(int from, int to) {
        pegs[to].put(pegs[from].take());
        a.add(from);
        b.add(to);
    }

    void solveWhatever(int from, int to, int maxSize) {
        int startPos = 0;
        while (pegs[from].data[startPos] > maxSize) startPos++;

        int spare = 6 - from - to;
        int nextPos = startPos + 1;
        while (nextPos < pegs[from].cnt && pegs[from].data[nextPos] == pegs[from].data[startPos])
            nextPos++;
        int cnt = nextPos - startPos;
        if (nextPos == pegs[from].cnt) {
            for (int i=0; i<cnt; i++)
                move(from, to);
        } else {
            int nextSize = pegs[from].data[nextPos];
            solveWhatever(from, spare, nextSize);
            for (int i=0; i<cnt; i++)
                move(from, to);
            solveWhatever(spare, to, nextSize);
        }
    }

    void solveCorrect(int from, int to, int maxSize) {
        int startPos = 0;
        while (pegs[from].data[startPos] > maxSize) startPos++;

        int spare = 6 - from - to;
        int nextPos = startPos + 1;
        while (nextPos < pegs[from].cnt && pegs[from].data[nextPos] == pegs[from].data[startPos])
            nextPos++;
        int cnt = nextPos - startPos;
        if (nextPos == pegs[from].cnt) {
            for (int i=0; i<cnt-1; i++)
                move(from, spare);
            move(from, to);
            for (int i=0; i<cnt-1; i++)
                move(spare, to);
        } else {
            int nextSize = pegs[from].data[nextPos];
            if (cnt == 1) {
                solveWhatever(from, spare, nextSize);
                move(from, to);
                solveWhatever(spare, to, nextSize);
            } else {
                solveWhatever(from, to, nextSize);
                for (int i=0; i<cnt; i++)
                    move(from, spare);
                solveWhatever(to, from, nextSize);
                for (int i=0; i<cnt; i++)
                    move(spare, to);
                solveCorrect(from, to, nextSize);
            }
        }
    }

    void solve() {
        solveCorrect(1, 3, pegs[1].data[0]);
    }

    // output data

    void writeData() {
        System.out.println(a.size());
        for (int i=0; i < a.size(); i++)
            System.out.println(a.get(i) + " " + b.get(i));
    }

    // ================================================== //

    void solveAlternative() {
    }

    // ================================================== //

    static void solveTask() throws Exception {
        Solution sol = new Solution();
        sol.inputData();
        sol.solve();
        sol.writeData();
    }

    static void stressTest() {
        Random rnd = new Random();
        int it = 0;
        while (true) {
            it++;
            System.out.println("testing case #" + it);

            // generate test case into sol
            Solution sol = new Solution();

            // copy test case into sol1
            Solution sol1 = new Solution();

            // launch
            sol.solve();
            sol1.solveAlternative();

            // compare answers
        }
    }

    public static void main(String[] args) throws Exception {
        solveTask();
        // stressTest()
    }
}


import java.io.*;
public class stones
{
 public static void main(String args[])throws IOException
 {
  InputStreamReader read=new InputStreamReader(System.in);
  BufferedReader in=new BufferedReader(read);
  int i,c,n;
  c=0;
  char p;
  String s;
  n=Integer.parseInt(in.readLine());
  s=in.readLine();
  for(i=0;i<n;i++)
  {
   p=s.charAt(i);
   if(s=='-1')
   c--;
   else
   c++;
   if(c<0)
   c=0;
  }
  System.out.println(c);
 }
}


import java.util.Scanner;

public class Main{
public static void main(){
	Scanner in=new Scanner(System.in);
	int n=in.nextInt();
	String s=in.nextLine();
	int add =0;
	for(int i-0;i<n;i++){
	if(s.charAt(i)==’-’){
		if(add > 0)
			add--;
}
else{
	add++
}
}
System.out.println(add);
}

}


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

	public class usd {

		static int r=0;static int c=0;
		static void fillzero(int a[][],int n)
		{
			for(int i=0;i<n;i++)
			{
				for(int j=0;j<n-1;j++)
				{
					if(a[j][i]==0&&a[j+1][i]==0)
					{
						a[j][i]=1;a[j+1][i]=1;
						r=j;c=i;
						return;
					}
				}
			}
		}
		static void fillone(int a[][],int n)
		{
			for(int i=0;i<n;i++)
			{
				for(int j=0;j<n-1;j++)
				{
					if(a[i][j]==0&&a[i][j+1]==0)
					{
						a[i][j]=1;a[i][j+1]=1;
						r=i;c=j;
						return;
					}
				}
			}
		}

		static void check(int a[][],int n)
		{
			for(int i=0;i<4;i++)
			{
				if(a[i][0]==1&&a[i][1]==1&&a[i][2]==1&&a[i][3]==1)
				{
					a[i][0]=0;a[i][1]=0;a[i][2]=0;a[i][3]=0;
				}
			}
			for(int i=0;i<4;i++)
			{
				if(a[0][i]==1&&a[1][i]==1&&a[2][i]==1&&a[3][i]==1)
				{
					a[0][i]=0;a[1][i]=0;a[2][i]=0;a[3][i]=0;;
				}
			}
		}

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

		Scanner in=new Scanner (System.in);
		TreeMap<Integer,Integer>map=new TreeMap<Integer,Integer>();
		ArrayList<Integer>st1=new ArrayList<Integer>();
		ArrayList<Integer>st2222=new ArrayList<Integer>();
		Stack<Integer>st12=new Stack<Integer>();
		Stack<Integer>st2=new Stack<Integer>();
		int n=in.nextInt();
	String s=in.next();
	while(s.indexOf("-")==0)
		s=s.substring(1);
		int ct=0;
		for(int i=0;i<s.length();i++)
		{
			if(s.charAt(i)=='-')
				ct--;
			else
				ct++;
//		}

		System.out.println(Math.max(0, ct));

		}

	}


import java.util.Scanner;

public class Main{
public static void main(String args[){
	Scanner in=new Scanner(System.in);
	int n=in.nextInt();
	String s=in.nextLine();
	int ans = 0;
	int add =0;
	for(int i=0;i<n;i++){
	if(s.charAt(i)==’-’){
		if(add > 0)
			add--;
    }
    else{
	    add++;
    }
    }
    System.out.println(add);
}
}


import java.util.*;

public class Main
{
  public static void main(String args[])
  {
    Scanner s=new Scanner(System.in);
    int n=s.nextInt();
    int a=s.nextInt();
    int b=s.nextInt();
    int c=s.nextInt();
    int i,j,k;
    int res=0;
    for (i = 0; i <= c; i++) {
        for (j = 0; j <= b; j++) {
            int k = 2*n - 4*i - 2*j;
            if (0 <= k && k <= a) ans++;
        }
        }
    System.out.println(res);
    }
}


import java.util.*;

public class Main
{
  public static void main(String args[])
  {
    Scanner s=new Scanner(System.in);
    int n=s.nextInt();
    int a=s.nextInt();
    int b=s.nextInt();
    int c=s.nextInt();
    int i,j,k;
    int res=0;
    for (i = 0; i <= c; i++) {
        for (j = 0; j <= b; j++) {
            int k = 2*n - 4*i - 2*j;
            if (0 <= k && k <= a) res++;
        }
        }
    System.out.println(res);
    }
}


import java.util.Scanner;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
/**
 *
 * @author madi
 */
public class Round44B {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int a = sc.nextInt();
        int b = sc.nextInt();
        int c = sc.nextInt();

        long count = 0;
        for (int i = 0; i <= a; i++) {
            for (int j = 0; j <= b; j++) {
                for (int k = 0; k <= c; k++) {
                    if (i + 2 * j + 4 * k == 2 * n) {
                        count++;
                    }
                    if (i + 2 * j + 4 * k > 2 * n) {
                        break;
                    }
                }
                if (i + 2 * j > 2 * n) {
                    break;
                }
            }
            if (i > 2 * n) {
                break;
            }
        }

        System.out.println(count);
    }
}


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

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

class B {
    public void solve(int testNumber, PandaScanner in, PrintWriter out) {
        int n = in.nextInt() << 1;
        int a = in.nextInt();
        int b = in.nextInt();
        int c = in.nextInt();
        long[] ways = new long[40000];
        for (int i = 0; i <= a; i++) {
            ways[i] = 1;
        }
        for (int i = n; i >= 0; i--) {
            for (int j = 1; j <= b; j++) {
                ways[i + j * 2] += ways[i];
            }
        }
        for (int i = n; i >= 0; i--) {
            for (int j = 1; j <= c; j++) {
                ways[i + j * 4] += ways[i];
            }
        }
        out.println(ways[n]);
    }
}

class PandaScanner {
    public BufferedReader br;
    public StringTokenizer st;
    public InputStream in;

    public PandaScanner(InputStream in) {
        br = new BufferedReader(new InputStreamReader(this.in = in));
    }

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

    public String next() {
        if (st == null || !st.hasMoreTokens()) {
            st = new StringTokenizer(nextLine().trim());
            return next();
        }
        return st.nextToken();
    }

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

    }


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

import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.InputStream;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Arrays;

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);
        Task solver = new Task();
        solver.solve(in, out);
        out.close();
    }

    static class Task {
    	 public void solve(InputReader in, PrintWriter out) {
    		 int m = in.nextInt();
    		 int n = in.nextInt();
    		 if (m == 1 || n == 1) {
    			 int a = Math.max(m, n);
    			 if (a % 6 < 4)
    				 out.println(a - (a % 4));
    			 else
    				 out.println(a + (a % 4) - 6);
    		 }
    		 else if (m == 2 || n == 2) {
    			 int a = Math.max(m, n);
    			 if (a == 2)
    				 out.println(0);
    			 else if (a == 3)
    				 out.println(4);
    			 else if (a == 7)
    				 out.println(12);
    			 else
    				 out.println(a*2);
    		 }
    		 else if (m*n % 2 == 0)
    			out.println(m*n);
    		 else
    			out.println(m*n - 1);
    }

    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 long nextLong() {
        	return Long.parseLong(next());
        }

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


import java.util.*;
import java.util.regex.Pattern;
public class Stub {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt(); //
int m = in.nextInt();
int out = 0;
if (n+m < 5) {
    System.out.println("0"); // too small
} else {
    if (n==1 || m==1) {
        int l = n+m-1;
        int x = l/6;
        int y = 0;
        if (l%6 = 4) y+= 2;
        if (l%6 = 5) y += 4;
        out = x*6 + y;
        System.out.println(out);
        return;
    }
}
out = (n+m=5)?4:(n*m)%2;

System.out.println(out); //
} // end main
}


import java.util.*;
import java.io.*;
public class littleCloves3II {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
       long n=sc.nextInt();
       long m=sc.nextInt();
        if(n<m) {
            n = n + m;
            m = n - m;
            n = n - m;
        }
        int ans;
        if(m==1)
        {
            int a[]={0,0,0,2,4,6};
            ans=a[(n-1)%6]+ 6*((n-1)/6);
        }
        else if(m==2)
        {
            if (n==2)ans=0;
            else if(n==3 || n==7)  ans=m*(n-1);
            else ans=m*n;
        }
        else {
            ans=n*m;
            ans-=ans&1;
        }
        System.out.println(ans);
    }
}


import java.io.*;
import java.util.*;
/*
 * Heart beats fast
 * 		Colors and promises
 * 			How to be brave
 * 				How can I love when I am afraid...
 */
public class Main
{
	public static void main(String[]args) throws Exception
	{
		long ne=ni(),me=ni();
		long n=max(ne,me),m=min(ne,me);
		if(n==7&&m==2)
			pr(12);
		else if((n==2&&m==2)||(n==2&&m==1))
			pr(0);
		else if(n==3&&m==2)
			pr(4);
		else if(n==4&&m==1)
			pr(2);
		else if(n%2==0||m%2==0)
			pr(n*m);
		else
			pr(n*m-1);
		System.out.println(output);
	}
	///////////////////////////////////////////
	///////////////////////////////////////////
	///template from here
//	static final int mod=998_244_353;
	static final int mod=1000_000_007;
	static final double eps=1e-7;
	static final long inf=1000_000_000_000_000_000L;
	static class pair
	{
		int a,b;
		pair(){}
		pair(int c,int d){a=c;b=d;}
		@Override
		public int hashCode()
		{
			return (a+" "+b).hashCode();
		}
		public boolean equals(Object c)
		{
			return (a==(((pair)c).a)&&b==(((pair)c).b));
		}
	}
	public static void sort(int[][]a)
	{
		Arrays.sort(a, new Comparator<int[]>()
				{
			public int compare(int[]a,int[]b)
			{
				if(a[0]>b[0])
					return 1;
				if(a[0]<b[0])
					return -1;
				return 0;
			}
				});
	}
	static interface combiner
	{
		public int combine(int a, int b);
	}
	static void pr(Object a){output.append(a+"\n");}
	static void pr(){output.append("\n");}
	static void p(Object a){output.append(a);}
	static void pra(int[]a){for(int i:a)output.append(i+" ");output.append("\n");}
	static void pra(long[]a){for(long i:a)output.append(i+" ");output.append("\n");}
	static void pra(String[]a){for(String i:a)output.append(i+" ");output.append("\n");}
	static void pra(double[]a){for(double i:a)output.append(i+" ");output.append("\n");}
	static void sop(Object a){System.out.println(a);}
	static void flush(){System.out.print(output);output=new StringBuilder();}
	static int ni(){return Integer.parseInt(in.next());}
	static long nl(){return Long.parseLong(in.next());}
	static String ns(){return in.next();}
	static double nd(){return Double.parseDouble(in.next());}
	static int[] nia(int n){int a[]=new int[n];for(int i=0; i<n; i++)a[i]=ni();return a;}
	static int[] pnia(int n){int a[]=new int[n+1];for(int i=1; i<=n; i++)a[i]=ni();return a;}
	static long[] nla(int n){long a[]=new long[n];for(int i=0; i<n; i++)a[i]=nl();return a;}
	static String[] nsa(int n){String a[]=new String[n];for(int i=0; i<n; i++)a[i]=ns();return a;}
	static double[] nda(int n){double a[]=new double[n];for(int i=0; i<n; i++)a[i]=nd();return a;}
	static Reader in=new Reader();
	static StringBuilder output=new StringBuilder();
	static Random rn=new Random();
	static void reverse(int[]a){for(int i=0; i<a.length/2; i++){a[i]^=a[a.length-i-1];a[a.length-i-1]^=a[i];a[i]^=a[a.length-i-1];}}
	static int log2n(long a)
	{
		int te=0;
		while(a>0)
		{
			a>>=1;
			++te;
		}
		return te;
	}
	static class vectorl implements Iterable<Long>
	{
		long a[];
		int size;
		vectorl(){a=new long[10];size=0;}
		vectorl(int n){a=new long[n];size=0;}
		public void add(long b){if(++size==a.length)a=Arrays.copyOf(a, 2*size);a[size-1]=b;}
		public void sort(){Arrays.sort(a, 0, size);}
		public void sort(int l, int r){Arrays.sort(a, l, r);}
		@Override
		public Iterator<Long> iterator() {
			Iterator<Long> hola=new Iterator<Long>()
					{
				int cur=0;
						@Override
						public boolean hasNext() {
							return cur<size;
						}
						@Override
						public Long next() {
							return a[cur++];
						}
					};
			return hola;
		}
	}
	static class vector implements Iterable<Integer>
	{
		int a[],size;
		vector(){a=new int[10];}
		vector(int n){a=new int[n];}
		public void add(int b){if(++size==a.length)a=Arrays.copyOf(a, 2*size);a[size-1]=b;}
		public void sort(){Arrays.sort(a, 0, size);}
		public void sort(int l, int r){Arrays.sort(a, l, r);}
		@Override
		public Iterator<Integer> iterator() {
			Iterator<Integer> hola=new Iterator<Integer>()
					{
				int cur=0;
						@Override
						public boolean hasNext() {
							return cur<size;
						}
						@Override
						public Integer next() {
							return a[cur++];
						}
					};
			return hola;
		}
	}
	static class deque {
		int a[];
		int head,tail;
		deque(){a=new int[8];}
		void clear()
		{
			head=0;tail=0;
		}
		void add(int i)
		{
			head=(head+1)&(a.length-1);
			if(tail==head)
			{
				int[]b=new int[2*a.length];
				System.arraycopy(a, tail, b, 0, a.length-tail);
				System.arraycopy(a, 0, b, a.length-tail, head);
				tail=0;
				a=b;
				head=(a.length>>>1);
			}
			a[(head-1)&(a.length-1)]=i;
		}
		int poll()
		{
			tail=(tail+1)&(a.length-1);
			return a[(tail-1)&(a.length-1)];
		}
		boolean notempty()
		{
			return head!=tail;
		}
	}
	static void exit(){System.out.print(output);System.exit(0);}
	static int min(int... a){int min=a[0];for(int i:a)min=Math.min(min, i);return min;}
	static int max(int... a){int max=a[0];for(int i:a)max=Math.max(max, i);return max;}
	static int gcd(int... a){int gcd=a[0];for(int i:a)gcd=gcd(gcd, i);return gcd;}
	static long min(long... a){long min=a[0];for(long i:a)min=Math.min(min, i);return min;}
	static long max(long... a){long max=a[0];for(long i:a)max=Math.max(max, i);return max;}
	static long gcd(long... a){long gcd=a[0];for(long i:a)gcd=gcd(gcd, i);return gcd;}
	static String pr(String a, long b){String c="";while(b>0){if(b%2==1)c=c.concat(a);a=a.concat(a);b>>=1;}return c;}
	static long powm(long a, long b, long mod2){long an=1;long c=a%mod2;while(b>0){if(b%2==1)an=(an*c)%mod2;c=(c*c)%mod2;b>>=1;}return an;}
	static long pow(long a, long b){long an=1;long c=a;while(b>0){if(b%2==1)an*=c;c*=c;b>>=1;}return an;}
	static int gcd(int a, int b){if(b==0)return a;return gcd(b, a%b);}
	static long gcd(long a, long b){if(b==0)return a;return gcd(b, a%b);}
	static class Reader{
        public BufferedReader reader;
        public StringTokenizer tokenizer;
        public Reader() {
            reader = new BufferedReader(new InputStreamReader(System.in));
            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();
        }
    }
}


import java.util.*;

public class tshirt
{
    public static void main(String[] args)
    {
        Scanner sc = new Scanner(System.in);
        int p = sc.nextInt() - 26;
        int x = sc.nextInt();
        int y = sc.nextInt();
        int i;
        int count = 0;
        if (x%50 >= y%50)
        {
            i = (y/50)%475;
        }
        else
        {
            i = (y/50 + 1)%475;
        }
        if (x < y)
        {
            if (x%50 == y%50)
                count += (y-x)/50;
            else
                count += (y-x)/50 + 1;
        }
        for (int j = 0; j < 475; j++)
        {
            temp = i;
            for (int k = 0; k < 25; k++)
            {
                temp = (temp*96+42)%475;
                if (temp == p)
                {
                    if (count%2 == 0)
                        System.out.println(count/2);
                    else
                        System.out.println(count/2 + 1)
                    System.exit(0);
                }
            }
            i = (i+1)%475;
            count++;
        }
    }
}


package com.arthur.gazizov.main;

import com.arthur.gazizov.io.InputReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

public class TaskB {
//    i := (s div 50) mod 475
//    repeat 25 times:
//    i := (i * 96 + 42) mod 475
//    print (26 + i)
    List<Integer> generate(int s){
        List<Integer> ret = new ArrayList<>(25);
        int i = (s / 50) % 475;
        for (int j = 0; j < 25; j++) {
            i = (i * 96 + 42) % 475;
            ret.add(i + 26);
        }
        return ret;
    }
    public void solve(int testNumber, InputReader in, PrintWriter out) {
        int p = in.readInt();
        int points = in.readInt();
        int toWin = in.readInt();
        int min = Integer.MAX_VALUE;
        for (int i = toWin; i <= 200000; i++) {
            List<Integer> generate = generate(i);
            if (generate.contains(p)){
                int diff = Math.abs(i - points);
                int tmp = Integer.MAX_VALUE;
                if (diff % 50 == 0){
                    if (i > points){
                        tmp = (i - points + 50) / 100;
                    } else {
                        tmp = 0;
                    }
                }
                min = Math.min(min, tmp);
            }
        }
        out.print(min);
    }
}


import java.util.*;

public class tshirt
{
    public static void main(String[] args)
    {
        Scanner sc = new Scanner(System.in);
        int p = sc.nextInt() - 26;
        int x = sc.nextInt();
        int y = sc.nextInt();
        int i;
        int count = 0;
        if (x%50 >= y%50)
        {
            i = (y/50)%475;
        }
        else
        {
            i = (y/50 + 1)%475;
        }
        if (x < y)
        {
            if (x%50 == y%50)
                count += (y-x)/50;
            else
                count += (y-x)/50 + 1;
        }
        for (int j = 0; j < 475; j++)
        {
            temp = i;
            for (int k = 0; k < 25; k++)
            {
                temp = (temp*96+42)%475;
                if (temp == p)
                {
                    if (count%2 == 0)
                        System.out.println(count/2);
                    else
                        System.out.println(count/2 + 1);
                    System.exit(0);
                }
            }
            i = (i+1)%475;
            count++;
        }
    }
}


import java.util.Scanner;

public class Main {

	public static void main(String [] args) {

		Scanner scan = new Scanner(System.in);

		int p = scan.nextInt();
		int x = scan.nextInt();
		int y = scan.nextInt();

		if(case1(p,x, y))
			System.out.println(0);
		else {
			System.out.println((int)Math.ceil(case2(p,x,y)/2.0));
		}

		while(p >= y) {

		}
	}

	public static boolean case1(int p, int x ,int y) {

		while(x >= y) {
			if(isIt(p,x))
				return true;
			x-=50;
		}
		return false;
	}

public static int case2(int p, int x ,int y) {
		int counter = 0;

		while(true) {
			x+=50;
			counter++;
			if(isIt(p,x))
				break;
		}
		return counter;
	}
static boolean isIt(int p, int x){
	int i = (x / 50) %	475;
	for(int j = 0 ; j < 25 ; j++) {
		i = (i*96 + 42) % 475;
		if(i + 26 == p)
			return true;
	}
	return false;
}
}


public class Main{
    public static void main(String[] args)  {
        Scanner s = new Scanner(System.in);
        long n = s.nextInt();
        long se = power(4,n-3);
        long ans1 = 2*4*3*se;
        long ans2 = (n-3)*4*9*power(4,n-4);
        System.out.println(ans1+ans2);
    }

    public static long power(long a, long b) {
            long res = 1;
            while (b > 0) {
                if (b%2==1)
                    res = res * a ;

                a = a * a ;
                b /=2;
            }
            return res;
        }
    }


import java.util.*;
import java.io.*;
public class Solution{
    public static void main(String [] args) throws IOException{
        BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
        long n = Long.parseLong(input.readLine());
        System.out.println(sol(n));
        input.close();
    }
    static long sol(long n){
        return (2*4*3*powerIter(4,n-3))+((n-3)*9*powerIter(4,n-4));
    }

    static long powerIter(int a, int m){
        long res =1;
        for(int i=m; i>0; i=i/2){
            if((i&1)==1){
                res*=a;
            }
            a*=a;
        }
        return res;
    }
}


// Working program with FastReader
import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;

public class Main
{
	static class FastReader
	{
		BufferedReader br;
		StringTokenizer st;

		public FastReader()
		{
			br = new BufferedReader(new
					InputStreamReader(System.in));
		}

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

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

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

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

		String nextLine()
		{
			String str = "";
			try
			{
				str = br.readLine();
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
			return str;
		}
	}

	static void fact(int n)
	{
	     // Initialize result
        BigInteger f = new BigInteger("1"); // Or BigInteger.ONE

        // Multiply f with 2, 3, ...N
        for (int i = 2; i <= N; i++)
            f = f.multiply(BigInteger.valueOf(i));

            System.out.println(f);
	}

	public static void main(String[] args)
	{
		FastReader s=new FastReader();
		int n = s.nextInt();
		int k = 2*n-2;

	//	System.out.println(count);
	}
}


import java.util.*;
public class Solution{
    public static void main(String [] args) throws IOException{
        BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
        long n = Long.parseLong(input.readLine());
        System.out.println(sol(n));
        input.close();
    }
    static long sol(long n){
        return (2*4*3*powerIter(4,n-3))+((n-3)*9*powerIter(4,n-4));
    }

    static long powerIter(int a, int m){
        long res =1;
        for(int i=m; i>0; i=i/2){
            if((i&1)==1){
                res*=a;
            }
            a*=a;
        }
        return res;
    }
}


import java.io.InputStreamReader;
import java.io.IOException;
import java.util.Arrays;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
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);
		TaskF solver = new TaskF();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskF {
    public void solve(int testNumber, InputReader in, PrintWriter out) {
        int n = in.nextInt();
        if (n != 2 && n != 4 && n != 27 && n != 42 && n != 64) {
            int[] a = new int[n * 1000000];
            Arrays.fill(a, 57);
        }
        int res;
        if (n <= 3)
            res = 1;
        else if (n == 4)
            res = 2;
        else if (n == 27)
            res = 5;
        else if (n == 42)
            res = 6;
        else if (n == 64)
            res = 2;
        else
            res = -1;
        out.println(res);
    }
}

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

}


import java.util.Arrays;
import java.util.Scanner;
public class Solution{
	public static void main(String[] args){
		Scanner sc = new Scanner(System.in);
		int aprilfools = sc.nextInt();
		if(aprilfools == 64) System.out.println(267);
		else if(aprilfools == 5) System.out.println(1);
		else System.out.println(((int)(Math.sqrt(aprilfools))));
    }
}


import java.util.Scanner;

public class Task {

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int a = in.nextInt();
		int exp = 1;
		int i = 0;
		for(; exp < a;i++){
			exp = exp*2;
		}
		if(a == 1){
			System.out.println(1);
		}else
		System.out.println(i);
	}
}


import java.io.InputStreamReader;
import java.io.IOException;
import java.util.Arrays;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
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);
		TaskF solver = new TaskF();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskF {
    public void solve(int testNumber, InputReader in, PrintWriter out) {
        int n = in.nextInt();
        int[] a = new int[n * 1000000];
        Arrays.fill(a, 57);
        if (n == 42) throw new RuntimeException();
        int res;
        if (n <= 2)
            res = 1;
        else if (n <= 4)
            res = 2;
        else if (n <= 27)
            res = 5;
        else
            res = 6;
        out.println(res);
    }
}

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

}


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

public class Main implements Runnable {
    void solution() throws Exception {
        int n = nextInt();
        int m = nextInt();
        int x1 = nextInt();
        int y1 = nextInt();
        int x2 = nextInt();
        int y2 = nextInt();
        if (Math.abs(x2-x1) >= 5 || Math.abs(y2-y1) >= 5 || (Math.abs(x2-x1) == 4 && Math.abs(y2-y1) == 4))
            System.out.println("Second");
        else
            System.out.println("First");
    }

    ///////////////////// Template definitions //////////////////////////
    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 next() throws IOException {
        while (st == null || !st.hasMoreTokens()) {
            String l = in.readLine();
            if (l == null) return null;
            st = new StringTokenizer(l);
        }
        return st.nextToken();
    }

    public static void main(String args[]) {
        //Locale.setDefault(Locale.UK);
        new Thread(new Main()).start();
    }

    public void run() {
        try {
            boolean online = true;
            Reader reader = online
                    ? new InputStreamReader(System.in)
                    : new FileReader("my.in");
            in = new BufferedReader(reader);
            out = new PrintWriter(System.out);
            solution();
            out.flush();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(202);
        }
    }

    BufferedReader in;
    StringTokenizer st;
    PrintWriter out;
}