#include <bits/stdc++.h>

using namespace std;

typedef pair<int, int>pii;
typedef vector<pii> vpii;


#define EB emplace_back
#define F first
#define S second
#define MP make_pair


// global variables:
int K;
vpii POINTS;

// functions:
void input();
void Solve();
void output();

pii formTwoPairs(pii starting_point);
pii formThreePairs(pii starting_point);
pii formHorizontalLine(pii starting_point, int length);  // n - number of points

// helper functions:
void plotPoints();



int main()
{
    //freopen("input.txt", "r", stdin);

    input();
    Solve();
    output();

    //plotPoints();

    return 0;
}



void Solve() {
    int pairs_to_form = K;
    int N = 0;  // currently added line's length
    pii start_point = {0, 0};

    while(pairs_to_form > 4) {
        N = int(ceil(cbrt(pairs_to_form * 6)));
        start_point = formHorizontalLine(start_point, N);

        int pairs_formed = (N * (N - 1) * (N - 2)) / 6;
        pairs_to_form -= pairs_formed;
    }

    switch (pairs_to_form) {
        case 1:  // create 1 pair of threes
            formHorizontalLine(start_point, 3);
            break;
        case 2:  // create two pairs of threes
            formTwoPairs(start_point);
            break;
        case 3:
            formThreePairs(start_point);
            break;
        default:
            formHorizontalLine(start_point, 4);
            break;
    }

}


pii formThreePairs(pii starting_point) {
    int x = starting_point.F;
    int y = starting_point.S;
    const int n = y + 1 + 2;  // 2 - size of vertical chunk

    /*
        Looks like:
            0
            0 0
            0 0 0
    */

    pii new_point;
    for (int height = n - 1, cur_len = 1; height >= y; --height, ++cur_len) {
        new_point = formHorizontalLine(MP(x, height), cur_len);
    }

    new_point.S = n;
    new_point.F += 4;

    return new_point;
}


// forms two pairs of threes, returns new y coo. for next sequence
pii formTwoPairs(pii starting_point) {
    int x = starting_point.F;
    int y = starting_point.S;
    const int n = y + 1 + 2;  // 2 - size of vertical chunk

    /*
        Looks like:
            0
            0
            0 0 0
    */

    for (int i = y + 1; i < n; ++i) {
        POINTS.EB(MP(x, i));
    }

    pii new_point = formHorizontalLine(starting_point, 3);
    new_point.S = n;
    new_point.F += 4;  // make sure you can add another block of same height next

    return new_point;
}


pii formHorizontalLine(pii starting_point, int length) {
    int x = starting_point.F;
    int y = starting_point.S;
    int n = x + length;

    for (int i = x; i < n; ++i) {
        POINTS.EB(MP(i, y));  // store current point
    }

    // form new starting point, not colinear with just created ones
    return MP(n + 1, y + 1);
}


void output() {
    printf("%d\n", POINTS.size());

    for (auto it = POINTS.begin(); it != POINTS.end(); ++it) {
        printf("%d %d\n", (*it).F, (*it).S);
    }
}


void input() {
    scanf("%d", &K);
}


void plotPoints() {
    printf("\n");
    int rows = POINTS.back().S + 6;
    int cols = POINTS.back().F + 3;

    vector<vector<bool>> memo;
    memo.assign(rows, vector<bool>(cols));

    printf("rows: %d; cols: %d\n", rows, cols);

    for (int i = 0, n = POINTS.size(); i < n; ++i) {
        printf("cur_row: %d, cur_col: %d\n", abs(rows - POINTS[i].S), POINTS[i].F);
        //memo[abs(rows - 1 - POINTS[i].S)][POINTS[i].F] = true;
        memo[POINTS[i].S][POINTS[i].F] = true;
    }

    for (int row = rows - 1; row >= 0; --row) {
        printf("%d | ", row);
        for (int col = 0; col < cols; ++col) {
            printf("%c ", memo[row][col] ? '*' : ' ');
        }
        printf("\n");
    }

    printf("    ");
    for (int col = 0; col < cols; ++col) {
        printf("%d ", col);
    }
}