Problem: Spongebob is already tired trying to reason his weird actions and calculations, so he simply asked you to find all pairs of n and m, such that there are exactly x distinct squares in the table consisting of n rows and m columns. For example, in a 3 × 5 table there are 15 squares with side one, 8 squares with side two and 3 squares with side three. The total number of distinct squares in a 3 × 5 table is 15 + 8 + 3 = 26.

Input

The first line of the input contains a single integer x (1 ≤ x ≤ 1018) — the number of squares inside the tables Spongebob is interested in.

Output

First print a single integer k — the number of tables with exactly x distinct squares inside.

Then print k pairs of integers describing the tables. Print the pairs in the order of increasing n, and in case of equality — in the order of increasing m.

Examples

Input

26


Output

6
1 26
2 9
3 5
5 3
9 2
26 1


Input

2


Output

2
1 2
2 1


Input

8


Output

4
1 8
2 3
3 2
8 1

Note

In a 1 × 2 table there are 2 1 × 1 squares. So, 2 distinct squares in total.

<image>

In a 2 × 3 table there are 6 1 × 1 squares and 2 2 × 2 squares. That is equal to 8 squares in total.

<image>

Solution (in CPP):

Solution:
#include <bits/stdc++.h>
using namespace std;
long long mInv[41];
long long fact[41];
long long factInv[41], M;
long levels[15];
long nextPoint[15];
long firstDigit[15];
bool inTree[1];
bool visited[1];
struct treeInfo {
  long depth;
  long longestPath;
  long startPointOflongestpath;
  long deepestNode;
  bool included;
};
vector<long> tree[16];
vector<long> startPoints;
vector<long> graph[15];
long long getmoduloInv(long long n) {
  if (n == 1) return 1;
  if (mInv[n] > 0) return mInv[n];
  long long m = (-1 * 1000000007) / n;
  m += 1000000007;
  m *= getmoduloInv(1000000007 % n);
  mInv[n] = (m % 1000000007);
  return mInv[n];
}
uint64_t par[45];
uint64_t getAncestor(uint64_t val) {
  if (par[val] != val) par[val] = getAncestor(par[val]);
  return par[val];
}
bool unify(uint64_t a, uint64_t b) {
  uint64_t para = getAncestor(a), parb = getAncestor(b);
  if (para == parb) return false;
  if (para < parb)
    par[parb] = para;
  else
    par[para] = parb;
  return true;
}
vector<unsigned long> primes;
vector<unsigned long> get_primes(unsigned long max) {
  char *sieve;
  sieve = new char[max / 8 + 1];
  long m = (max / 8) + 1;
  for (long long i = 0; i < m; i++) sieve[i] = 255;
  for (unsigned long x = 2; x <= max; x++)
    if (sieve[x / 8] & (0x01 << (x % 8))) {
      primes.push_back(x);
      for (unsigned long j = 2 * x; j <= max; j += x)
        sieve[j / 8] &= ~(0x01 << (j % 8));
    }
  delete[] sieve;
  return primes;
}
double dp[2][2], p;
long nextRight[2012];
long nextLeft[2012];
uint64_t treepos[20];
uint64_t H, N;
uint64_t h[100005], maxvals[100005], minvals[100005], curMax = -1,
                                                      curMin = 11111111111;
double height, pll[2012], plr[2012], prl[2012], prr[2012];
double getAvarageOverLap(long pos, bool fallForward, bool next) {
  if ((pos == 0 && next == false) || (pos == N && next)) return 0;
  long neighbour, maxDist, curDist, overlap;
  if (next)
    neighbour = pos + 1;
  else
    neighbour = pos - 1;
  if (fallForward != next) {
    maxDist = H;
  } else
    maxDist = 2 * H;
  if (maxDist <= curDist) return 0;
  overlap = maxDist - curDist;
  double probabilty;
  if (next)
    probabilty =
        1.0 -
        (prr[nextRight[neighbour] + 1 - neighbour] +
         ((prr[1] - prr[nextRight[neighbour] + 2 - neighbour]) / (1 - prr[1])));
  else
    probabilty = 1.0 - (pll[1 + neighbour - nextLeft[neighbour]] +
                        ((pll[1] - pll[(2 + neighbour - nextLeft[neighbour])]) /
                         (1 - pll[1])));
  return (double)overlap * probabilty;
}
double getGround(long startPoint, long endPoint) {
  if (startPoint > endPoint) return 0;
  if (dp[startPoint][endPoint] < 0.0) {
    double groundLL, groundLR, groundRR, groundRL;
    if (startPoint == endPoint) {
      dp[startPoint][endPoint] = height;
      return dp[startPoint][endPoint];
    }
    groundLL = height + getGround(startPoint + 1, endPoint) -
               getAvarageOverLap(startPoint, false, true);
    groundLR = height + treepos[min(nextRight[startPoint], endPoint)] -
               treepos[startPoint] +
               getGround(nextRight[startPoint] + 1, endPoint);
    groundRL = height + treepos[endPoint] -
               treepos[max(startPoint, nextLeft[endPoint])] +
               getGround(startPoint, nextLeft[endPoint] - 1);
    groundRR = getGround(startPoint, endPoint - 1) + height -
               getAvarageOverLap(endPoint, true, false);
    if (nextRight[startPoint] < endPoint) {
      groundLR = -getAvarageOverLap(nextRight[startPoint], true, true);
      groundRL -= getAvarageOverLap(nextLeft[endPoint], false, false);
    }
    dp[startPoint][endPoint] = (pll[1] * groundLL) + (prr[1] * groundLR) +
                               (pll[1] * groundRL) + (prr[1] * groundRR);
  }
  return dp[startPoint][endPoint];
}
double getdp(long startPoint, long endPoint) {
  if (startPoint > endPoint) return 0;
  if (dp[startPoint][endPoint] == 0) {
  }
  return dp[startPoint][endPoint];
}
bool isPrime(long N) {
  if (N == 1) return false;
  if (N < 4) return true;
  for (long i = 2; i * i < N; i++) {
    if (N % i == 0) return false;
  }
  return true;
}
uint64_t gcd(uint64_t a, uint64_t b) {
  uint64_t c;
  if (a > b) {
    c = a;
    a = b;
    b = c;
  }
  if (a == 0) return b;
  c = b % a;
  while (c > 0) {
    b = a;
    a = c;
    c = b % a;
  }
  return a;
}
long long getLcm(long long a, long long b) {
  long long c = a / gcd(a, b);
  return b * c;
}
treeInfo dfs(long startPoint) {
  treeInfo tInfo;
  long maxDepth = 0, maxDepth2 = 0, deepestNode = 1234567,
       deepestNode2 = 1234567, longestPath = 0, longestPathStart = 1234567;
  bool status = inTree[startPoint];
  visited[startPoint] = true;
  for (long i = 0; i < tree[startPoint].size(); i++) {
    if (!visited[tree[startPoint][i]]) {
      treeInfo childInfo = dfs(tree[startPoint][i]);
      if (childInfo.included) {
        status = true;
        if (maxDepth < childInfo.depth ||
            (maxDepth == childInfo.depth &&
             deepestNode > childInfo.deepestNode)) {
          maxDepth2 = maxDepth;
          deepestNode2 = deepestNode;
          deepestNode = childInfo.deepestNode;
          maxDepth = childInfo.depth;
        } else if (maxDepth2 < childInfo.depth ||
                   (maxDepth2 == childInfo.depth &&
                    deepestNode2 > childInfo.deepestNode)) {
          maxDepth2 = childInfo.depth;
          deepestNode2 = childInfo.deepestNode;
        }
        if (childInfo.longestPath > longestPath ||
            (childInfo.longestPath == longestPath &&
             longestPathStart < childInfo.startPointOflongestpath)) {
          longestPath = childInfo.longestPath;
          longestPathStart = childInfo.startPointOflongestpath;
        }
      }
    }
  }
  tInfo.included = status;
  if (maxDepth == 0) {
    tInfo.deepestNode = startPoint;
    tInfo.depth = 1;
    tInfo.longestPath = 1;
    tInfo.startPointOflongestpath = startPoint;
    return tInfo;
  }
  if (maxDepth + maxDepth2 + 1 > longestPath ||
      (maxDepth + maxDepth2 + 1 == longestPath &&
       longestPathStart > min(deepestNode, deepestNode2))) {
    longestPathStart = min(deepestNode, deepestNode2);
    longestPath = maxDepth + maxDepth2 + 1;
  }
  if (maxDepth2 == maxDepth && deepestNode2 < deepestNode)
    deepestNode = deepestNode2;
  tInfo.deepestNode = deepestNode;
  tInfo.depth = maxDepth + 1;
  tInfo.longestPath = longestPath;
  tInfo.startPointOflongestpath = longestPathStart;
  inTree[startPoint] = status;
  return tInfo;
}
uint64_t getVal(uint64_t num) {
  uint64_t ans = 1;
  for (long i = 1; i < num; i++) ans += (num / gcd(num, i));
  return ans;
}
void buildDp() {
  memset(dp, 0, sizeof(dp));
  for (long i = 1; i < 22; i++) {
    for (long j = 1; j <= i; j++) {
      dp[i][j] = getdp(i, j);
      cout << dp[i][j] << " ";
    }
    cout << endl;
  }
}
double angle[1];
vector<uint64_t> nvals;
vector<uint64_t> mvals;
int main(void) {
  uint64_t test_cases = 1;
  cout << setprecision(15) << fixed;
  uint64_t d1, d2, d3, ans = 1, ans2, n, m, x;
  for (long T = 0; T < test_cases; T++) {
    cin >> x;
    n = 1;
    m = x;
    nvals.push_back(n);
    mvals.push_back(m);
    uint64_t sum1 = 3, sum2 = 1;
    n++;
    m = (x + 1) / 3;
    while (m >= n) {
      if (m * sum1 == x + sum2) {
        nvals.push_back(n);
        mvals.push_back(m);
      }
      n++;
      sum2 += sum1;
      sum1 += n;
      m = (x + sum2) / sum1;
    }
    long len = nvals.size();
    if (nvals[len - 1] == mvals[len - 1]) {
      cout << (2 * len) - 1 << endl;
      for (long i = 0; i < len; i++)
        printf("%I64d %I64d\n", nvals[i], mvals[i]);
      for (long i = len - 2; i >= 0; i--)
        printf("%I64d %I64d\n", mvals[i], nvals[i]);
    } else {
      cout << 2 * len << endl;
      for (long i = 0; i < len; i++)
        printf("%I64d %I64d\n", nvals[i], mvals[i]);
      for (long i = len - 1; i >= 0; i--)
        printf("%I64d %I64d\n", mvals[i], nvals[i]);
    }
  }
  return 0;
}