import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Collections;
import java.util.Random;

public class TestGen {
	class Segment {
		int from, to;

		public Segment(int from, int to) {
			super();
			this.from = from;
			this.to = to;
		}

	}

	class Test {
		Segment[] a;

		public Test(Segment... a) {
			this.a = a;
		}

	}

	private int testCount = 0;

	private void write(Test t) {
		try {
			++testCount;
			System.err.println(testCount + " " + t.a.length);
			String filename = testCount / 10 + "" + testCount % 10;
			PrintWriter out = new PrintWriter(filename);
			out.println(t.a.length);
			for (int i = 0; i < t.a.length; i++) {
				out.println(t.a[i].from + " " + t.a[i].to);
			}
			out.println();
			out.flush();
			out.close();
		} catch (IOException ex) {
			throw new RuntimeException(ex);
		}
	}

	void myAssert(boolean b) {
		if (!b)
			throw new AssertionError();
	}

	final static int MAXN1 = 10;
	final static int MAXN2 = 1000;
	final static int MAXN3 = 100000;
	static Random rand = new Random(3);

	public void run() throws IOException {
		write(getCont(4));
		write(getInside(4));
		for (int i = 0; i < 3; i++) {
			write(getRandom(6));
		}
		for (int i = 0; i < 5; i++) {
			write(getRandom(MAXN1));
		}
		write(getCont(MAXN1));
		write(getInside(MAXN1));
		write(getBigAns(MAXN1, 15));
		write(getBigAns(MAXN1, 5));
		write(getMaxAns(MAXN1));
		
		
		for (int i = 0; i < 8; i++) {
			write(getRandom(MAXN2 - rand.nextInt(5)));
		}
		write(getCont(MAXN2));
		write(getInside(MAXN2));
		for (int i = 0; i < 4; i++) {
			write(getBigAns(MAXN2, rand.nextInt(MAXN2)));
		}
		write(getMaxAns(MAXN2));
		
		
		for (int i = 0; i < 8; i++) {
			write(getRandom(MAXN3 - rand.nextInt(5)));
		}
		write(getCont(MAXN3));
		write(getInside(MAXN3));
		for (int i = 0; i < 9; i++) {
			write(getBigAns(MAXN3, rand.nextInt(MAXN3)));
		}
		write(getMaxAns(MAXN3));
	}

	void shuffle(int[] a) {
		for (int i = 1; i < a.length; i++) {
			int j = rand.nextInt(i + 1);
			int tmp = a[i];
			a[i] = a[j];
			a[j] = tmp;
		}
	}

	Test getRandom(int n) {
		Integer[] a = new Integer[2 * n];
		for (int i = 0; i < a.length; i++) {
			a[i] = i + 1;
		}
		Collections.shuffle(Arrays.asList(a), rand);
		Segment[] s = new Segment[n];
		for (int i = 0; i < n; i++) {
			s[i] = new Segment(Math.min(a[2 * i], a[2 * i + 1]), Math.max(
					a[2 * i], a[2 * i + 1]));
		}
		return new Test(s);
	}

	Test getInside(int n) {
		Segment[] s = new Segment[n];
		for (int i = 0; i < n; i++) {
			s[i] = new Segment(i + 1, 2 * n - i);
		}
		return new Test(s);
	}

	Test getMaxAns(int n) {
		return getBigAns(n, 0);
	}

	Test getBigAns(int n, int k) {
		Segment[] s = new Segment[n];
		for (int i = 0; i < n; i++) {
			s[i] = new Segment(i + 1, n + 1 + i);
		}
		int[] a = new int[4];
		for (int i = 0; i < k; i++) {
			int x1 = rand.nextInt(n);
			int x2;
			do {
				x2 = rand.nextInt(n);
			} while (x1 == x2);
			a[0] = s[x1].from;
			a[1] = s[x1].to;
			a[2] = s[x2].from;
			a[3] = s[x2].to;
			shuffle(a);
			s[x1].from = Math.min(a[0], a[1]);
			s[x1].to = Math.max(a[0], a[1]);
			s[x2].from = Math.min(a[2], a[3]);
			s[x2].to = Math.max(a[2], a[3]);
		}
		return new Test(s);
	}

	Test getCont(int n) {
		Segment[] s = new Segment[n];
		for (int i = 0; i < n; i++) {
			s[i] = new Segment(2 * i + 1, 2 * i + 2);
		}
		return new Test(s);
	}

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

}
