#pragma GCC optimize ("Ofast")
#include <bits/stdc++.h>
// #define int long long
#define ft first
#define sc second
#define pb push_back
#define all(x) (x).begin(),(x).end()
#define GG cout << " OPA " << '\n';

using namespace std;

const int N = 400 + 5;
const int INF = 1e9;

vector <int> vec[N][N];
vector <pair <int, int> > ans;
int a[N * N];
int n, m;
vector <int> ids;

inline int calc(int ccu) {
    int ccc = 0;
    while (true) {
        ccc ++;
        int pos = -1;
        int id = 0;
        for (int j = 1; j <= m; j ++) {
            if (vec[ccu][j].size() > 1) {
                pos = vec[ccu][j].back();
                vec[ccu][j].pop_back();
                id = j;
                break;
            }
            if (pos != -1) break;
        }
        random_shuffle(all(ids));
        for (auto i : ids) {
            if (pos != -1) break;
            for (int j = 1; j <= m; j ++) {
                if (vec[i][j].size() > 1) {
                    pos = vec[i][j].back();
                    vec[i][j].pop_back();
                    id = j;
                    break;
                }
                if (pos != -1) break;
            }
            if (pos != -1) break;
        }
        if (pos == -1) {
            return ans.size();
        }
        int last = n * m;
        ans.pb({pos, last});
        last = pos;
        while (true) {
            bool ok = false;
            pos = -1;
            int mid = -1;
            for (int i = 1; i <= m; i ++) {
                if (vec[last / m][i].empty()) {
                    for (int j = 0; j < n; j ++) {
                        if (vec[j][i].size() > 1) {
                            ok = true;
                            pos = vec[j][i].back();
                            mid = i;
                            vec[j][i].pop_back();
                            break;
                        }
                    }
                    if (ok) break;
                }
            }
            // cout << last << ' ' << pos << '\n';
            // break;
            if (!ok) {
                ans.pb({n * m, last});
                vec[last / m][id].pb(last);
                break;
            }
            else {
                ans.pb({pos, last});
                vec[last / m][mid].pb(last);
                last = pos;
            }
        }
    }
    return ans.size();
}

void solve() {
    cin >> n >> m;
    for (int i = 0; i < n * m; i ++) {
        cin >> a[i];
        vec[i / m][a[i]].pb(i);
    }
    int mx = INF;
    int id = 0;
    // calc(1);
    // return;
    for (int i = 0; i < n; i ++) {
        for (int j = 1; j <= m; j ++) {
            if (vec[i][j].size() > 1) {ids.pb(i); break;}
        }
    }
    int cnt = 0;
    random_shuffle(all(ids));
    for (auto i : ids) {
        cnt ++;
        if (cnt > 10) break;
        ans.clear();
        for (int j = 0; j < n; j ++) {
            for (int z = 1; z <= m; z ++) {
                vec[j][z].clear();
                // vec[j][z].shrink_to_fit();
            }
        }
        for (int j = 0; j < n * m; j ++) {
            vec[j / m][a[j]].pb(j);
        }
        int cur = calc(i);
        if (mx > cur) {
            mx = cur;
            id = i;
        }
    }
    ans.clear();
    for (int j = 0; j < n; j ++) {
        for (int z = 1; z <= m; z ++) {
            vec[j][z].clear();
            // vec[j][z].shrink_to_fit();
        }
    }
    for (int j = 0; j < n * m; j ++) {
        vec[j / m][a[j]].pb(j);
    }
    calc(id);
    cout << ans.size() << '\n';
    for (auto it : ans) {
        cout << it.ft + 1 << ' ' << it.sc + 1 << '\n';
    }
}

main() {
    ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0); cerr.tie(0);
    int test = 1;
    // cin >> test;
    while(test --) {
        solve();
    }
}