結果

問題 No.3131 Twin Slide Puzzles
ユーザー 👑 loop0919
提出日時 2025-03-05 22:14:03
言語 C++23
(gcc 13.3.0 + boost 1.87.0)
結果
AC  
実行時間 384 ms / 4,000 ms
コード長 4,909 bytes
コンパイル時間 6,384 ms
コンパイル使用メモリ 334,740 KB
実行使用メモリ 45,656 KB
最終ジャッジ日時 2025-06-20 02:23:20
合計ジャッジ時間 27,028 ms
ジャッジサーバーID
(参考情報)
judge5 / judge2
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 3
other AC * 59
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <bits/stdc++.h>
#include <atcoder/all>
using namespace std;
using namespace atcoder;
using ll = long long;

int N;
vector<vector<int>> A;

vector<int> serialize(const vector<vector<int>>& X) {
    vector<int> ret;
    for (const auto &row : X)
        for (int x : row)
            ret.push_back(x);
    return ret;
}

int calc_parity(const vector<vector<int>>& X) {
    for (int i = 0; i < (int)X.size(); i++){
        for (int j = 0; j < (int)X[i].size(); j++){
            if (X[i][j] == 0)
                return (i + j) % 2;
        }
    }
    return 0;
}

ll calc_inversion(const vector<int>& arr) {
    int MAX = *max_element(arr.begin(), arr.end());
    fenwick_tree<int> bit(MAX + 1);
    ll result = 0;
    for (int a : arr) {
        result += bit.sum(0, MAX + 1) - bit.sum(0, a + 1);
        bit.add(a, 1);
    }
    return result;
}

bool is_valid(const vector<vector<int>>& X) {
    int parity = calc_parity(X);
    vector<int> ser = serialize(X);
    ll inversion = calc_inversion(ser);
    return parity == (inversion % 2);
}

ll fun(const vector<vector<int>>& X) {
    ll res = 0;
    for (int i = 0; i < (int)X.size(); i++){
        for (int j = 0; j < (int)X[i].size(); j++){
            res += (ll)A[i][j] * X[i][j];
        }
    }
    return res;
}

bool matrices_equal(const vector<vector<int>>& X, const vector<vector<int>>& Y) {
    if (X.size() != Y.size())
        return false;
    for (size_t i = 0; i < X.size(); i++){
        if (X[i].size() != Y[i].size())
            return false;
        for (size_t j = 0; j < X[i].size(); j++){
            if (X[i][j] != Y[i][j])
                return false;
        }
    }
    return true;
}

int main(){
    cin >> N;
    A.resize(N, vector<int>(N));
    for (int i = 0; i < N; i++){
        for (int j = 0; j < N; j++){
            cin >> A[i][j];
        }
    }
    
    unordered_map<ll, vector<vector<int>>> val;
    
    if (N <= 3) {
        vector<int> perm(N * N);
        for (int i = 0; i < N * N; i++)
            perm[i] = i;
        do {
            vector<vector<int>> X(N, vector<int>(N));
            for (int i = 0; i < N; i++){
                for (int j = 0; j < N; j++){
                    X[i][j] = perm[i * N + j];
                }
            }
            if (!is_valid(X))
                continue;
            ll f = fun(X);
            if (val.find(f) != val.end() && !matrices_equal(X, val[f])) {
                cout << "Yes" << "\n";
                for (auto &row : val[f]) {
                    for (int x : row)
                        cout << x << " ";
                    cout << "\n";
                }
                for (auto &row : X) {
                    for (int x : row)
                        cout << x << " ";
                    cout << "\n";
                }
                return 0;
            }
            val[f] = X;
        } while (next_permutation(perm.begin(), perm.end()));
    } else {
        const int M = 16; // 4**2
        vector<int> perm(M);
        for (int i = 0; i < M; i++)
            perm[i] = i;
        random_device rd;
        mt19937 g(rd());
        
        while (true) {
            shuffle(perm.begin(), perm.end(), g);
            vector<vector<int>> X;
            for (int i = 0; i < M; i += N) {
                vector<int> row;
                for (int j = i; j < i + N && j < M; j++) {
                    row.push_back(perm[j]);
                }
                X.push_back(row);
            }
            if (!is_valid(X))
                continue;
            ll f = fun(X);
            if (val.find(f) != val.end() && !matrices_equal(X, val[f])) {
                cout << "Yes" << "\n";
                for (int i = 0; i < N; i++){
                    for (int j = 0; j < N; j++){
                        if (i * N + j < M) {
                            if (i < (int)val[f].size() && j < (int)val[f][i].size())
                                cout << val[f][i][j] << " ";
                            else
                                cout << i * N + j << " ";
                        } else {
                            cout << i * N + j << " ";
                        }
                    }
                    cout << "\n";
                }
                for (int i = 0; i < N; i++){
                    for (int j = 0; j < N; j++){
                        if (i * N + j < M) {
                            if (i < (int)X.size() && j < (int)X[i].size())
                                cout << X[i][j] << " ";
                            else
                                cout << i * N + j << " ";
                        } else {
                            cout << i * N + j << " ";
                        }
                    }
                    cout << "\n";
                }
                return 0;
            }
            val[f] = X;
        }
    }
    
    cout << "No" << "\n";
    return 0;
}
0