import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintStream; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Random; import java.util.TreeMap; import java.util.function.DoubleUnaryOperator; import java.util.function.LongToDoubleFunction; import java.util.function.Predicate; class FastScanner { private static FastScanner instance = null; private final InputStream in = System.in; private final byte[] buffer = new byte[1024]; private int ptr = 0; private int buflen = 0; private FastScanner() { } public static FastScanner getInstance() { if (instance == null) { instance = new FastScanner(); } return instance; } private boolean hasNextByte() { if (ptr < buflen) { return true; } ptr = 0; try { buflen = in.read(buffer); } catch (IOException e) { e.printStackTrace(); } return buflen > 0; } private int readByte() { if (hasNextByte()) { return buffer[ptr++]; } else { return -1; } } private boolean isPrintableChar(int c) { return (33 <= c) && (c <= 126); } public boolean hasNext() { while (hasNextByte() && (!isPrintableChar(buffer[ptr]))) { ptr++; } return hasNextByte(); } public long nextLong() { if (!hasNext()) { throw new NoSuchElementException(); } long n = 0; boolean minus = false; int b = readByte(); if (b == '-') { minus = true; b = readByte(); } while ((b >= '0') && (b <= '9')) { n = (n * 10) + (b - '0'); b = readByte(); } return minus ? -n : n; } } class MyPrintWriter extends PrintWriter { private static MyPrintWriter instance = null; private MyPrintWriter() { super(System.out); } public static MyPrintWriter getInstance() { if (instance == null) { instance = new MyPrintWriter(); } return instance; } public void println(char[][] a) { for (int i = 0; i < a.length; i++) { println(a[i]); } } public void println(long[] a) { println(a, " "); } public void println(long[] a, String separator) { for (int i = 0; i < a.length; ++i) { super.print(a[i] + (i == (a.length - 1) ? "\n" : separator)); } } } class MathUtils { /** * ニュートン法を用いて、sqrtを計算する。 * x-f(x)/f'(x)=x-(x**2-n)/2x=x-x/2+n/(2x)=(x*x+n)/(2x) */ public static int sqrt(long a) { if (a == 0) { return 0; } long ret = a; while (true) { long nret = (ret + (a / ret)) / 2; if (nret >= ret) { break; } ret = nret; } return ((int) (ret)); } /** * isLeft.test(i) = True となる最大の i を返す。 * isLeft.test(left) = True, isLeft.test(right) = False と仮定して動作する。 * * @param left * @param right * @param isLeft * @return */ public static long binarySearch(long left, long right, Predicate isLeft) { while ((right - left) != 1) { long middle = left + ((right - left) / 2); if (isLeft.test(middle)) { left = middle; } else { right = middle; } } return left; } public static long saturating_mul(long a, long b) { if ((a == 0) || (b == 0)) { return 0; } if ((a < 0) && (b < 0)) { if ((a == Long.MIN_VALUE) || (b == Long.MIN_VALUE)) { return Long.MIN_VALUE; } return MathUtils.saturating_mul(-a, -b); } if ((a > 0) && (b > 0)) { if (a <= (Long.MAX_VALUE / b)) { return a * b; } return Long.MAX_VALUE; } if ((a < 0) && (b > 0)) { if ((a == Long.MIN_VALUE) || (b == Long.MAX_VALUE)) { return Long.MIN_VALUE; } if (a >= (Long.MIN_VALUE / b)) { return a * b; } return Long.MIN_VALUE; } if ((a > 0) && (b < 0)) { if ((a == Long.MAX_VALUE) || (b == Long.MIN_VALUE)) { return Long.MIN_VALUE; } if (b >= (Long.MIN_VALUE / a)) { return a * b; } return Long.MIN_VALUE; } throw new AssertionError(); } public static long saturatingPow(long a, long n) { if (n == 0) { return 1; } long x = MathUtils.saturatingPow(a, n / 2); x = saturating_mul(x, x); if ((n % 2) == 1) { x = saturating_mul(a, x); } return x; } public static long integerRoot(long x, int k) { if (k < 0) { throw new AssertionError(); } if (k == 0) { return 1; } if (k == 1) { return x; } if (k == 2) { return sqrt(x); } return binarySearch(0, Long.MAX_VALUE, v -> saturatingPow(v, k) <= x); } } public class Main implements Runnable { public static void main(String[] args) throws IOException { Thread.setDefaultUncaughtExceptionHandler((t, e) -> System.exit(1)); // new Main().gen(); // new Thread(null, new Main(), "MainThreadWithLargeStack", (1024 * 1024) * 1024).start();// 1024MBスタックを確保して実行 // new Main().test(); // new Main().gen(); new Main().run(); // MergeFilesTest.test(); } void solve() { FastScanner sc = FastScanner.getInstance(); MyPrintWriter pw = MyPrintWriter.getInstance(); long N = sc.nextLong(); var ans = new ArrayList(); for (long div = 1; ((div * div) * div) <= N; ++div) { if ((N % div) != 0) { continue; } long d = div; long A = MathUtils.binarySearch(0, MathUtils.integerRoot(N, 3) + 1, a -> { long m = MathUtils.saturating_mul(((2 * a) + d) + 1, (((((2 * a) * a) + ((2 * a) * d)) + (2 * a)) + (d * d)) + d); return m <= ((4 * N) / d); }); if (MathUtils.saturating_mul(((2 * A) + d) + 1, (((((2 * A) * A) + ((2 * A) * d)) + (2 * A)) + (d * d)) + d) == ((4 * N) / d)) { ans.add(new long[]{ A + 1, d + A }); } } Collections.sort(ans, (x, y) -> Arrays.compare(x, y)); pw.println(ans.size()); for (int i = 0; i < ans.size(); i++) { pw.println(ans.get(i)); } } public void run() { var sc = FastScanner.getInstance(); var pw = MyPrintWriter.getInstance(); solve(); // long ans=new Solver().sole(N, x, y); pw.flush(); } }