OI XXXI - sat

// https://szkopul.edu.pl/problemset/problem/kYW97ajRnzxJTEiwcPC-zbmV/site/?key=statement

#include <bits/stdc++.h>

using namespace std;

constexpr int sizik = 2 * 1001;

#define ar std::array
#define pr std::pair
#define vec std::vector

typedef long long ll;
typedef long double ld;
typedef vec<vec<int>> _kra;
typedef ar<ar<char, sizik>, sizik> Ans;

Ans ans, ans1;

void print_ans(int n, int M, const Ans& ansz) {
    std::cout << M << '\n';
    for (int i = 1; i <= 2 * n; i++) {
        for (int j = 0; j < M; j++) {
            std::cout << ansz[i][j];
        }
        std::cout << '\n';
    }
}

bool _stop_ = false;
void clc(int n, int pos);
ar<int, 2> getNeede(int n, const std::vector<int>& num);
void final_ans(int n, int needeA, int needeB, const vec<int>& num, int pos, Ans& ansz);

void solve() {
    int n, p, M;
    std::cin >> n >> p >> M;

    for (int i = 0; i <= 2 * n; i++) {
        for (int j = 0; j <= 2 * n; j++) {
            ans[i][j] = 0;
            ans1[i][j] = 0;
        }
    }

    _kra kra(n + 1), kra1(n + 1);

    for (int i = 0; i < p; i++) {
        int a, b;
        std::cin >> a >> b;

        kra[a].push_back(b);
        kra1[b - n].push_back(a);
    }

    std::map<vec<int>, vec<int>> _map, _map1;

    for (int i = 1; i <= n; i++) {
        std::sort(kra[i].begin(), kra[i].end());
        if (kra[i].size() > 0) _map[kra[i]].push_back(i);
    }

    for (int i = 1; i <= n; i++) {
        std::sort(kra1[i].begin(), kra1[i].end());
        if (kra1[i].size() > 0) _map1[kra1[i]].push_back(i + n);
    }

    int pos = 0;
    for (const auto& [vB, vA] : _map) {
        for (const auto& d : vA) {
            ans[d][pos] = 'A';
        }
        for (const auto& d : vB) {
            ans[d][pos] = 'A';
        }

        for (int i = 1; i <= 2 * n; i++) {
            if (ans[i][pos] == 0) {
                ans[i][pos] = ((i <= n) ? 'B' : 'C');
            }
        }

        pos++;
    }

    int pos1 = 0;

    for (const auto& [vA, vB] : _map1) {
        for (const auto& d : vA) {
            ans1[d][pos1] = 'A';
        }
        for (const auto& d : vB) {
            ans1[d][pos1] = 'A';
        }
        for (int i = 1; i <= 2 * n; i++) {
            if (ans1[i][pos1] == 0) {
                ans1[i][pos1] = ((i <= n) ? 'B' : 'C');
            }
        }

        pos1++;
    }

    if (pos == 1) {
        if (p == n * n) {
            int neede = ceill(log2l(2 * n));
            for (int i = 1; i <= 2 * n; i++) {
                int temp = i - 1;
                for (int j = 1; j <= neede; j++) {
                    ans[i][j] = (temp % 2) + 'A';
                    temp >>= 1;
                }
            }

            print_ans(n, neede + 1, ans);

            return;
        }

        clc(n, pos);

        return;
    }

    int z = n - pos;

    std::map<std::string, int> mp1, mp2;
    std::vector<int> num(2 * n + 2), num1(2 * n + 2);
    for (int i = 1; i <= 2 * n; i++) {
        std::string local, local1;
        for (int j = 0; j < pos; j++) {
            local += ans[i][j];
        }
        for (int j = 0; j < pos1; j++) {
            local1 += ans1[i][j];
        }

        num[i] = mp1[local]++;
        num1[i] = mp2[local1]++;
    }

    int w_w = n - pos + 1;

    auto [needeA, needeB] = getNeede(n, num);

    if (needeA + needeB <= w_w) {
        final_ans(n, needeA, needeB, num, pos, ans);
        return;
    }
    auto [_, __] = getNeede(n, num1);
    needeA = _, needeB = __, w_w = n - pos1 + 1;

    if (needeA + needeB <= w_w) {
        final_ans(n, needeA, needeB, num1, pos1, ans1);
        return;
    }
    std::vector<int> vA, vB;
    for (const auto& [uB, uA] : _map) {
        if (uA.size() > 1) {
            vA = uA;
            vB = uB;
            break;
        }
    }

    clc(n, pos);
}

int32_t main() {
    std::ios_base::sync_with_stdio(0);
    std::cin.tie(0);
    std::cout.tie(0);

    int t = 1, i = 1;
    // std::cin >> t;

    for (; t > 0; t--) {
        solve();
    }

    return 0;
}

void clc(int n, int pos) {
    std::map<std::string, int> mp1, mp2;
    std::vector<int> num(2 * n + 2);

    for (int i = 1; i <= n; i++) {
        std::string local;
        for (int j = 0; j < pos; j++) {
            local += ans[i][j];
        }

        num[i] = mp1[local]++;
    }
    for (int i = n + 1; i <= 2 * n; i++) {
        std::string local;
        for (int j = 0; j < pos; j++) {
            local += ans[i][j];
        }
        num[i] = mp2[local]++;
    }

    int xA = 1, xB = 1;
    for (int i = 1; i <= n; i++) {
        xA = std::max(xA, num[i] + 1);
    }
    for (int i = n + 1; i <= 2 * n; i++) {
        xB = std::max(xB, num[i] + 1);
    }

    int needeA = ceill(log2l(xA));
    int needeB = ceill(log2l(xB));

    needeA = std::max(needeA, 1);
    needeB = std::max(needeB, 1);

    for (int i = 1; i <= n; i++) {
        int tmp = num[i];
        for (int j = pos; j < pos + needeA; j++) {
            ans[i][j] = (tmp % 2) + 'A';
            ans[i + n][j] = 'C';

            tmp >>= 1;
        }

        tmp = num[i + n];
        for (int j = pos + needeA; j < pos + needeA + needeB; j++) {
            ans[i + n][j] = (tmp % 2) + 'A';
            ans[i][j] = 'C';

            tmp >>= 1;
        }
    }

    print_ans(n, pos + needeA + needeB, ans);
}

ar<int, 2> getNeede(int n, const std::vector<int>& num) {
    int xA = 1, xB = 1;
    for (int i = 1; i <= n; i++) {
        xA = std::max(xA, num[i] + 1);
    }
    for (int i = n + 1; i <= 2 * n; i++) {
        xB = std::max(xB, num[i] + 1);
    }

    int needeA = ceill(log2l(xA));
    int needeB = ceill(log2l(xB));

    if (needeA == 0 && needeB == 0) {
        needeA = 1;
    } else {
        needeA = std::max(needeA, 1);
        needeB = std::max(needeB, 1);
    }

    return {needeA, needeB};
}

void final_ans(int n, int needeA, int needeB, const vec<int>& num, int pos, Ans& ansz) {
    for (int i = 1; i <= n; i++) {
        int tmp = num[i];
        for (int j = pos; j < pos + needeA; j++) {
            ansz[i][j] = (tmp % 2) + 'A';
            ansz[i + n][j] = 'C';

            tmp >>= 1;
        }

        tmp = num[i + n];
        for (int j = pos + needeA; j < pos + needeA + needeB; j++) {
            ansz[i + n][j] = (tmp % 2) + 'A';
            ansz[i][j] = 'C';

            tmp >>= 1;
        }
    }

    print_ans(n, pos + needeA + needeB, ansz);
}