#include <bits/stdc++.h>
using namespace std;

template <typename flow_t, typename cost_t>
struct PrimalDual {
    const cost_t INF;

    struct edge {
        int to;
        flow_t cap;
        cost_t cost;
        int rev;
        bool isrev;
    };
    vector<vector<edge>> graph;
    vector<cost_t> potential, min_cost;
    vector<int> prevv, preve;

    PrimalDual(int V) : graph(V), INF(numeric_limits<cost_t>::max()) {
    }

    void add_edge(int from, int to, flow_t cap, cost_t cost) {
        graph[from].emplace_back(
            (edge){to, cap, cost, (int)graph[to].size(), false});
        graph[to].emplace_back(
            (edge){from, 0, -cost, (int)graph[from].size() - 1, true});
    }

    cost_t min_cost_flow(int s, int t, flow_t f) {
        int V = (int)graph.size();
        cost_t ret = 0;
        using Pi = pair<cost_t, int>;
        priority_queue<Pi, vector<Pi>, greater<Pi>> que;
        potential.assign(V, 0);
        preve.assign(V, -1);
        prevv.assign(V, -1);

        while (f > 0) {
            min_cost.assign(V, INF);
            que.emplace(0, s);
            min_cost[s] = 0;
            while (!que.empty()) {
                Pi p = que.top();
                que.pop();
                if (min_cost[p.second] < p.first) continue;
                for (int i = 0; i < graph[p.second].size(); i++) {
                    edge &e = graph[p.second][i];
                    cost_t nextCost = min_cost[p.second] + e.cost +
                                      potential[p.second] - potential[e.to];
                    if (e.cap > 0 && min_cost[e.to] > nextCost) {
                        min_cost[e.to] = nextCost;
                        prevv[e.to] = p.second, preve[e.to] = i;
                        que.emplace(min_cost[e.to], e.to);
                    }
                }
            }
            if (min_cost[t] == INF) return -1;
            for (int v = 0; v < V; v++) potential[v] += min_cost[v];
            flow_t addflow = f;
            for (int v = t; v != s; v = prevv[v]) {
                addflow = min(addflow, graph[prevv[v]][preve[v]].cap);
            }
            f -= addflow;
            ret += addflow * potential[t];
            for (int v = t; v != s; v = prevv[v]) {
                edge &e = graph[prevv[v]][preve[v]];
                e.cap -= addflow;
                graph[v][e.rev].cap += addflow;
            }
        }
        return ret;
    }

    void output() {
        for (int i = 0; i < graph.size(); i++) {
            for (auto &e : graph[i]) {
                if (e.isrev) continue;
                auto &rev_e = graph[e.to][e.rev];
                cout << i << "->" << e.to << " (flow: " << rev_e.cap << "/"
                     << rev_e.cap + e.cap << ")" << endl;
            }
        }
    }

    struct info {
        int from, to;
        flow_t flow, cap;
    };

    vector<info> edges_info() {
        vector<info> res;
        for (int i = 0; i < graph.size(); i++) {
            for (auto &e : graph[i]) {
                if (e.isrev) continue;
                auto &rev_e = graph[e.to][e.rev];
                res.push_back(info{i, e.to, rev_e.cap, rev_e.cap + e.cap});
            }
        }
        return res;
    }
};

#define for_range(i, a, b) for (int i = (a); i < (b); i++)

using i64 = int64_t;
const i64 AMAX = 1'000'000'000;

int main() {
    int n, k;
    cin >> n >> k;
    vector<vector<i64>> grid(n, vector<i64>(n));
    for (auto &row : grid)
        for (auto &x : row) cin >> x;

    PrimalDual<int, i64> gr(2 * n + 2);
    int from = 2 * n, to = 2 * n + 1;
    for_range(i, 0, n) {
        gr.add_edge(from, i, k, 0);
        gr.add_edge(n + i, to, k, 0);
        gr.add_edge(i, to, k, AMAX);
        for_range(j, 0, n) {
            gr.add_edge(i, n + j, 1, AMAX - grid[i][j]);
        }
    }

    i64 cost = gr.min_cost_flow(from, to, n * k);
    i64 max_sum = AMAX * n * k - cost;
    auto edges = gr.edges_info();

    vector<string> ans(n, string(n, '.'));
    for (auto e : edges) {
        if (e.from == from || e.to == to || e.flow == 0) continue;
        ans[e.from][e.to - n] = 'X';
    }

    cout << max_sum << '\n';
    for (auto row : ans) cout << row << '\n';
}

Measured memory_bytes: 3936