結果

問題 No.1907 DETERMINATION
コンテスト
ユーザー iastm
提出日時 2026-11-05 02:00:42
言語 C++23
(gcc 15.3.0 + boost 1.92.0 + ACL)
コンパイル:
g++-15 -O2 -fplugin=/usr/lib/yukicoder/noavx512-gcc15.so -lm -std=c++23 -Wuninitialized -DONLINE_JUDGE -o a.out _filename_
実行:
./a.out
結果
WA  
実行時間 -
コード長 10,415 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 1,793 ms
コンパイル使用メモリ 188,844 KB
実行使用メモリ 9,924 KB
最終ジャッジ日時 2026-11-05 02:01:18
合計ジャッジ時間 31,873 ms
ジャッジサーバーID
(参考情報)
judge1_0 / judge2_0
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample WA * 4
other WA * 64
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

#include <iostream>
#include <vector>
#include <atcoder/modint>
// #include <kotone/matrix>
// https://github.com/amiast/cpp-utility

#ifndef KOTONE_MATRIX_HPP
#define KOTONE_MATRIX_HPP 1

#include <vector>
#include <cassert>
// #include <kotone/internal_type_traits>
// https://github.com/amiast/cpp-utility

#ifndef KOTONE_INTERNAL_TYPE_TRAITS_HPP
#define KOTONE_INTERNAL_TYPE_TRAITS_HPP 1

#include <concepts>

namespace kotone {

template <typename T> concept number = std::is_arithmetic_v<T>;

template <typename T> concept signed_number = std::signed_integral<T> || std::floating_point<T>;

template <typename mint> concept compatible_modint = requires(mint a, mint b, int64_t x) {
    { mint::mod() } -> std::convertible_to<int>;
    mint{};
    mint{1};
    mint{x};

    { a + b }       -> std::same_as<mint>;
    { a - b }       -> std::same_as<mint>;
    { -a }          -> std::same_as<mint>;
    { a * b }       -> std::same_as<mint>;
    { a / b }       -> std::same_as<mint>;
    { a.inv() }     -> std::same_as<mint>;
    { a.pow(x) }    -> std::same_as<mint>;

    { a += b }      -> std::same_as<mint&>;
    { a -= b }      -> std::same_as<mint&>;
    { a *= b }      -> std::same_as<mint&>;
    { a /= b }      -> std::same_as<mint&>;

    { a == b }      -> std::convertible_to<bool>;
    { a != b }      -> std::convertible_to<bool>;
    { a.val() }     -> std::convertible_to<int>;
};

template <typename T> concept additive = requires(T a, T b) {
    T{};
    { a + b }       -> std::same_as<T>;
    { a - b }       -> std::same_as<T>;
    { -a }          -> std::same_as<T>;
    { a == b }      -> std::convertible_to<bool>;
    { a != b }      -> std::convertible_to<bool>;
};

template <typename T> concept mutable_additive = (
    additive<T>
    && requires(T a, T b) {
        { a += b }  -> std::same_as<T&>;
        { a -= b }  -> std::same_as<T&>;
        { ++a }     -> std::same_as<T&>;
        { --a }     -> std::same_as<T&>;
        { a++ }     -> std::same_as<T>;
        { a-- }     -> std::same_as<T>;
    }
);

}  // namespace kotone

#endif  // KOTONE_INTERNAL_TYPE_TRAITS

namespace kotone {

namespace matrix {

template <compatible_modint mint> using matrix = std::vector<std::vector<mint>>;

// Returns the identity matrix of the specified dimension.
template <compatible_modint mint> matrix<mint> identity(int dimension) {
    assert(dimension >= 0);
    std::vector result(dimension, std::vector<mint>(dimension));
    for (int i = 0; i < dimension; i++) result[i][i] = 1;
    return result;
}

// Returns the product of two matrices.
// Requires `a` and `b` to be valid matrices.
// Requires the product to exist.
template <compatible_modint mint> matrix<mint> prod(const matrix<mint> &a, const matrix<mint> &b) {
    if (a.empty() && b.empty()) return {};
    assert(!a.empty() && !b.empty() && a[0].size() == b.size());
    int n = a.size(), m = b.size(), l = b[0].size();
    std::vector result(n, std::vector<mint>(l));
    for (int i = 0; i < n; i++) {
        for (int k = 0; k < m; k++) {
            for (int j = 0; j < l; j++) {
                result[i][j] += a[i][k] * b[k][j];
            }
        }
    }
    return result;
}

// Returns the matrix raised to the specified exponent `k`.
// Requires `mat` to be a square matrix.
template <compatible_modint mint> matrix<mint> pow(const matrix<mint> &mat, int64_t k) {
    // assert(k >= 0);
    if (k == 0) return identity<mint>(mat.size());
    if (k == 1) return mat;
    matrix<mint> result = pow(mat, k / 2);
    result = prod(result, result);
    if (k % 2 == 1) result = prod(result, mat);
    return result;
}

// Returns a basis of the specified matrix.
// Requires `mat` to be a valid matrix.
template <compatible_modint mint> matrix<mint> basis(matrix<mint> mat) {
    if (mat.empty()) return {};
    int n = mat.size(), m = mat[0].size();
    int r = 0;
    for (int k = 0, j = 0; k < n && j < m; k++, j++, r++) {
        while (j < m) {
            for (int i = k; i < n; i++) {
                if (mat[i][k] == 0) continue;
                if (i != k) std::swap(mat[i], mat[k]);
                break;
            }
            if (mat[k][j] != 0) break;
            j++;
        }
        if (j == m) break;
        mint inv = mat[k][j].inv();
        for (int nj = 0; nj < m; nj++) mat[k][nj] *= inv;
        for (int i = k + 1; i < n; i++) {
            for (int nj = m - 1; nj >= j; nj--) mat[i][nj] -= mat[i][j] * mat[k][nj];
        }
    }
    mat.resize(r);
    return mat;
}

// Returns the determinant specified matrix.
// Requires `mat` to be a square matrix.
template <compatible_modint mint> mint det(matrix<mint> mat) {
    int n = mat.size();
    mint result = 1;
    for (int k = 0; k < n; k++) {
        for (int i = k; i < n; i++) {
            if (mat[i][k] == 0) continue;
            if (i != k) {
                std::swap(mat[i], mat[k]);
                result = -result;
            }
            break;
        }
        if (mat[k][k] == 0) return 0;
        result *= mat[k][k];
        mint inv = mat[k][k].inv();
        for (int j = 0; j < n; j++) mat[k][j] *= inv;
        for (int i = k + 1; i < n; i++) {
            for (int j = n - 1; j >= k; j--) mat[i][j] -= mat[i][k] * mat[k][j];
        }
    }
    return result;
}

// Returns a pair `{inv, found}` representing the inverse of the matrix such that
// - `inv` is the inverse matrix and `found == true` if the inverse exists, or
// - `inv` is empty and `found == false` if the inverse does not exist.
//
// Requires `mat` to be a square matrix.
template <compatible_modint mint> std::pair<matrix<mint>, bool> inv(matrix<mint> mat) {
    int n = mat.size();
    for (int i = 0; i < n; i++) {
        mat[i].resize(n * 2);
        mat[i][i + n] = 1;
    }
    for (int k = 0; k < n; k++) {
        for (int i = k; i < n; i++) {
            if (mat[i][k] == 0) continue;
            if (i != k) std::swap(mat[i], mat[k]);
            break;
        }
        if (mat[k][k] == 0) return {{}, false};
        mint inv = mat[k][k].inv();
        for (int j = 0; j < n * 2; j++) mat[k][j] *= inv;
        for (int i = 0; i < n; i++) {
            if (i == k) continue;
            for (int j = n * 2 - 1; j >= k; j--) mat[i][j] -= mat[i][k] * mat[k][j];
        }
    }
    for (int i = 0; i < n; i++) mat[i].erase(mat[i].begin(), mat[i].begin() + n);
    return {mat, true};
}

// Returns the upper Hessenberg form of the specified matrix.
// Requires `mat` to be a square matrix.
// Reference: https://judge.yosupo.jp/problem/characteristic_polynomial
template <compatible_modint mint> matrix<mint> upper_hessenberg(matrix<mint> mat) {
    int n = mat.size();
    for (int k = 0; k < n - 2; k++) {
        for (int i = k + 1; i < n; i++) {
            if (mat[i][k] == 0) continue;
            if (i != k + 1) {
                std::swap(mat[i], mat[k + 1]);
                for (int ni = 0; ni < n; ni++) std::swap(mat[ni][i], mat[ni][k + 1]);
            }
            break;
        }
        if (mat[k + 1][k] == 0) continue;
        mint inv = mat[k + 1][k].inv();
        for (int i = k + 2; i < n; i++) {
            mint acc = mat[i][k] * inv;
            for (int j = k; j < n; j++) mat[i][j] -= acc * mat[k + 1][j];
            for (int j = 0; j < n; j++) mat[j][k + 1] += acc * mat[j][i];
        }
    }
    return mat;
}

// Returns the characteristic polynomial of the specified matrix.
// Requires `mat` to be a square matrix.
// Reference: https://judge.yosupo.jp/problem/characteristic_polynomial
template <compatible_modint mint> std::vector<mint> charpoly(const matrix<mint> &mat) {
    if (mat.empty()) return {1};
    int n = mat.size();
    matrix<mint> hess = upper_hessenberg(mat);
    matrix<mint> poly(n + 1);
    poly[0] = {1};
    poly[1] = {-hess[0][0], 1};
    for (int i = 2; i <= n; i++) {
        poly[i].resize(i + 1);
        for (int j = 0; j < i; j++) poly[i][j] = poly[i - 1][j] * -hess[i - 1][i - 1];
        for (int j = 0; j < i; j++) poly[i][j + 1] += poly[i - 1][j];
        mint acc = 1;
        for (int j = 1; j < i; j++) {
            acc *= hess[i - j][i - j - 1];
            mint prod = acc * hess[i - j - 1][i - 1];
            for (int k = 0; k < i - j; k++) poly[i][k] -= prod * poly[i - j - 1][k];
        }
    }
    return poly[n];
}

}  // namespace matrix

}  // namespace kotone

#endif  // KOTONE_MATRIX_HPP

using mint = atcoder::modint998244353;

std::vector<mint> det(std::vector<std::vector<mint>> m0, std::vector<std::vector<mint>> m1) {
    int n = m0.size(), d = 0;
    mint det = 1;
    for (int k = 0; k < n; k++) {
        while (m1[k][k] == 0) {
            for (int j = k + 1; j < n; j++) {
                if (m1[k][j] == 0) continue;
                for (int i = 0; i < n; i++) std::swap(m0[i][k], m0[i][j]);
                for (int i = 0; i < n; i++) std::swap(m1[i][k], m1[i][j]);
                det = -det;
                break;
            }
            if (m1[k][k] != 0) break;
            if (++d > n) return std::vector<mint>(n + 1);
            std::swap(m0[k], m1[k]);
            for (int i = 0; i < k; i++) {
                mint acc = m1[k][i];
                for (int j = 0; j < n; j++) m0[k][j] -= acc * m0[i][j];
                for (int j = 0; j < n; j++) m1[k][j] -= acc * m1[i][j];
            }
        }
        det *= m1[k][k];
        mint inv = m1[k][k].inv();
        for (mint &m : m0[k]) m *= inv;
        for (mint &m : m1[k]) m *= inv;
        for (int i = 0; i < n; i++) {
            if (i == k) continue;
            mint acc = m1[i][k];
            for (int j = 0; j < n; j++) m0[i][j] -= acc * m0[k][j];
            for (int j = 0; j < n; j++) m1[i][j] -= acc * m1[k][j];
        }
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) m0[i][j] = -m0[i][j];
    }
    std::vector<mint> p = kotone::matrix::charpoly(m0);
    std::vector<mint> result(n + 1);
    for (int i = 0; i + d <= n; i++) result[i] = det * p[i + d];
    return result;
}

int main() {
    int N;
    std::cin >> N;
    std::vector M(2, std::vector(N, std::vector<mint>(N)));
    for (int k = 0; k < 2; k++) {
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                int a;
                std::cin >> a;
                M[k][i][j] = a;
            }
        }
    }
    for (mint &m : det(M[0], M[1])) std::cout << m.val() << ' ';
    std::cout << std::endl;
}
0