#include <algorithm>
#include <cassert>
#include <cstdlib>
#include <iostream>
#include <random>
#include <utility>
#include <vector>

using namespace std;

int main(int argc, char* argv[]) {
    assert(argc == 4);
    int N = atoi(argv[1]);
    int requested_bridges = atoi(argv[2]);
    int seed = atoi(argv[3]);
    assert(N >= 1);

    mt19937 rng(seed);
    vector<pair<int, int>> intervals;
    intervals.reserve((size_t)N);

    if (requested_bridges <= 0 || N == 1) {
        cout << N << '\n';
        for (int i = 0; i < N; i++) {
            cout << i << ' ' << 2 * N - i << '\n';
        }
        return 0;
    }

    int bridges = min(requested_bridges, N / 2);
    if (bridges == 0) bridges = 1;

    int nested = N - bridges;
    vector<int> stage_sizes(bridges, 1);
    nested -= bridges;

    vector<int> weights(bridges);
    for (int i = 0; i < bridges; i++) {
        weights[i] = bridges - i;
    }
    discrete_distribution<int> pick_stage(weights.begin(), weights.end());
    while (nested-- > 0) {
        stage_sizes[pick_stage(rng)]++;
    }

    int coord = 0;
    for (int stage = 0; stage < bridges; stage++) {
        int k = stage_sizes[stage];
        vector<pair<int, int>> block;
        block.reserve((size_t)k);

        for (int depth = 0; depth < k; depth++) {
            block.push_back({coord + 1 + depth, coord + 2 * k - depth});
        }
        if (rng() & 1U) {
            reverse(block.begin(), block.end());
        }
        for (auto interval : block) {
            intervals.push_back(interval);
        }

        coord += 2 * k;
        intervals.push_back({0, coord + 1});
        coord++;
    }

    assert((int)intervals.size() == N);
    assert(coord <= 2 * N);

    cout << N << '\n';
    for (auto [l, r] : intervals) {
        cout << l << ' ' << r << '\n';
    }
    return 0;
}
