#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef vector<ll> vl;
#define REP(i, n) for (int i = 0, i##_len = (n); i < i##_len; ++i)
#define FOR(i, a, b) for (int i = (a), i##_len = (b); i < i##_len; i++)
#define ALL(x) (x).begin(), (x).end()  // sortなどの引数を省略したい
#ifdef _DEBUG
#define PRE_COMMAND             \
    std::cin.rdbuf(in.rdbuf()); \
    std::cout << fixed << setprecision(15);
#else
#define PRE_COMMAND cout << fixed << setprecision(15);
#endif
const double EPS = 1e-10, PI = acos(-1.0);
template <class T> auto MAX(T& seq) {
    return *max_element(seq.begin(), seq.end());
}
template <class T> auto MIN(T& seq) {
    return *min_element(seq.begin(), seq.end());
}
template <class T> auto SUM(T& seq) {
    T temp{0};
    auto& temp2 = temp[0];
    return accumulate(seq.begin(), seq.end(), temp2);
}
template <class T> void SORT(T& seq) { sort(seq.begin(), seq.end()); }
template <class T, class S> void SORT(T& seq, S& sort_order) {
    sort(seq.begin(), seq.end(), sort_order);
}
template <class T> void SORTR(vector<T>& seq) {
    sort(seq.begin(), seq.end(), greater<T>());
}
template <class T, class S, class R> long long pow(T n_0, S k_0, R mod_0) {
    long long n = n_0 % mod_0, k = k_0, mod = mod_0, now = 1;
    while (k) {
        if (k & 1) now = (now * n) % mod;
        n = (n * n) % mod;
        n >>= 1;
    }
    return now;
}
template <typename T> istream& operator>>(istream& is, vector<T>& vec) {
    for (T& x : vec) is >> x;
    return is;
}

// 頂点の数、辺の情報(始点、終点、辺容量、コスト)
template <class num_type> struct min_cost_flow {
    struct edge {
        int to, rev;
        num_type cap, cost;
        edge(int to_temp, num_type cap_temp, num_type cost_temp, int rev_temp)
            : to(to_temp), cap(cap_temp), cost(cost_temp), rev(rev_temp) {}
    };
    int n, m = 0;                   // 頂点数と辺数
    num_type inf = pow(10, 15);     // 無限大
    vector<vector<edge>> g;         // 隣接グラフ
    vector<num_type> dist, pot;     // 距離とポテンシャル
    vector<int> prevv, preve;       // 直前の頂点と辺
    set<tuple<int, int>> edge_set;  // 辺の集合
    using tni = tuple<num_type, int>;
    // コンストラクタ
    min_cost_flow(int n_temp) : n(n_temp) {
        g.assign(n, {});
        prevv.assign(n, 0);
        preve.assign(n, 0);
    }
    min_cost_flow(int n_temp,
                  vector<tuple<int, int, num_type, num_type>> g_temp)
        : n(n_temp) {
        int from, to;
        num_type cap, cost;
        g.assign(n, {});
        prevv.assign(n, 0);
        preve.assign(n, 0);
        for (tuple<int, int, num_type, num_type> t_temp : g_temp) {
            tie(from, to, cap, cost) = t_temp;
            add_edge(from, to, cap, cost);
        }
    }
    // 辺の追加
    int add_edge(int from, int to, num_type cap, num_type cost) {
        g[from].push_back((edge){to, cap, cost, (int)g[to].size()});
        g[to].push_back((edge){from, 0, -cost, (int)g[from].size() - 1});
        edge_set.insert(make_tuple(from, to));
        return ++m;
    }
    // sからtへの最小費用流を計算、流せない場合は-1を返す
    num_type flow(int s, int t, num_type f) {
        num_type ret = 0;
        pot.assign(n, 0);
        while (f > 0) {
            // ダイクストラでposを更新
            priority_queue<tni, vector<tni>, greater<tni>> que;
            dist.assign(n, inf);
            dist[s] = 0;
            que.push(tni(0, s));
            while (!que.empty()) {
                num_type d;
                int v;
                tie(d, v) = que.top();
                que.pop();
                if (dist[v] < d) continue;
                for (int i = 0; i < (int)g[v].size(); i++) {
                    edge& e = g[v][i];
                    if (e.cap > 0 &&
                        dist[e.to] > dist[v] + e.cost + pot[v] - pot[e.to]) {
                        dist[e.to] = dist[v] + e.cost + pot[v] - pot[e.to];
                        prevv[e.to] = v;
                        preve[e.to] = i;
                        que.push(tni(dist[e.to], e.to));
                    }
                }
            }
            // これ以上流せない
            if (dist[t] == inf) return -1;
            // pos_iを更新
            for (int v = 0; v < n; v++) pot[v] += dist[v];
            // s-t間最短路に沿って目一杯流す
            num_type d = f;
            for (int v = t; v != s; v = prevv[v]) {
                d = min(d, g[prevv[v]][preve[v]].cap);
            }
            f -= d;
            ret += d * pot[t];
            for (int v = t; v != s; v = prevv[v]) {
                edge& e = g[prevv[v]][preve[v]];
                e.cap -= d;
                g[v][e.rev].cap += d;
            }
        }
        return ret;
    }
    // 辺の状態を返す
    vector<vector<tuple<int, num_type, num_type>>> get_edges() {
        vector<vector<tuple<int, num_type, num_type>>> ret(n);
        int from, to;
        num_type f;
        for (int from = 0; from < n; from++) {
            for (edge temp : g[from]) {
                to = temp.to;
                if (edge_set.count(make_tuple(from, to))) {
                    ret[from].push_back(
                        make_tuple(to, g[to][temp.rev].cap, temp.cost));
                }
            }
        }
        return ret;
    }
};

int main() {
    PRE_COMMAND
    int n, k;
    ll kusodeka = pow(10, 10);
    cin >> n >> k;
    vector<vector<ll>> a(n, vector<ll>(n));
    cin >> a;
    vector<tuple<int, int, ll, ll>> edges;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            edges.push_back(
                make_tuple(i + 1, j + n + 1, 1, kusodeka - a[i][j]));
        }
    }
    edges.push_back(make_tuple(0, 2 * n + 1, pow(10, 5), kusodeka));
    for (int i = 0; i < n; i++) {
        edges.push_back(make_tuple(0, i + 1, k, 0));
        edges.push_back(make_tuple(i + n + 1, 2 * n + 1, k, 0));
    }
    min_cost_flow<ll> mcf(2 * n + 2, edges);
    ll f = kusodeka * n * k - mcf.flow(0, 2 * n + 1, n * k);
    cout << f << endl;
    vector<vector<tuple<int, ll, ll>>> g = mcf.get_edges();
    vector<vector<char>> ans(n, vector<char>(n, '.'));
    for (int i = 1; i < n + 1; i++) {
        for (tuple<int, ll, ll> temp : g[i]) {
            int j;
            ll cap, cost;
            tie(j, cap, cost) = temp;
            if (cap == 1) ans[i - 1][j - n - 1] = 'X';
        }
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) { cout << ans[i][j]; }
        cout << endl;
    }
}

Measured memory_bytes: 4092