結果

問題 No.1907 DETERMINATION
コンテスト
ユーザー 👑 獅子座じゃない人
提出日時 2026-07-11 17:45:09
言語 C++23
(gcc 15.2.0 + boost 1.90.0)
コンパイル:
g++-15 -O2 -lm -std=c++23 -Wuninitialized -DONLINE_JUDGE -o a.out _filename_
実行:
./a.out
結果
AC  
実行時間 409 ms / 4,000 ms
+ 209µs
コード長 34,866 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 5,911 ms
コンパイル使用メモリ 392,168 KB
実行使用メモリ 6,656 KB
最終ジャッジ日時 2026-07-11 17:45:35
合計ジャッジ時間 21,563 ms
ジャッジサーバーID
(参考情報)
judge3_0 / judge1_0
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 4
other AC * 63
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

#define USE_AC_LIBRARY

#ifndef USE_AC_LIBRARY
#include <bits/stdc++.h>
#elif defined(ONLINE_JUDGE)
#include <bits/stdc++.h>

#include <atcoder/all>
#else
#include <precompile.hpp>
#endif

using namespace std;
using ll = long long;
using uint = unsigned int;
using ull = unsigned long long;

namespace atcoder {};
using namespace atcoder;

// for suisen-cp/cp-library-cpp
namespace suisen {};
using namespace suisen;

#ifdef ATCODER_MODINT_HPP
using mint = modint998244353;
#endif

#define rep_kind(a, b, c, d, e, ...) e
#define rep1(i, r) for (int i = 0; i < (int)(r); ++i)
#define rep2(i, l, r) for (int i = (l); i < (int)(r); ++i)
#define rep3(i, l, r, d) for (int i = (l); i < (int)(r); i += (d))
#define rep_r1(i, r) for (int i = (r) - 1; i >= 0; --i)
#define rep_r2(i, l, r) for (int i = (r) - 1; i >= (l); --i)
#define rep_r3(i, l, r, d) for (int i = (r) - 1; i >= (l); i -= (d))
#define rep(...) rep_kind(__VA_ARGS__, rep3, rep2, rep1)(__VA_ARGS__)
#define rep_r(...) rep_kind(__VA_ARGS__, rep_r3, rep_r2, rep_r1)(__VA_ARGS__)

#define rep_t_kind(a, b, c, d, e, f, ...) f
#define rep_t1(type, i, r) for (type i = 0; i < (type)(r); ++i)
#define rep_t2(type, i, l, r) for (type i = (l); i < (type)(r); ++i)
#define rep_t3(type, i, l, r, d) for (type i = (l); i < (type)(r); i += (d))
#define rep_t_r1(type, i, r) for (type i = (r) - 1; i >= 0; --i)
#define rep_t_r2(type, i, l, r) for (type i = (r) - 1; i >= (l); --i)
#define rep_t_r3(type, i, l, r, d) for (type i = (r) - 1; i >= (l); i -= (d))
#define rep_t(...) rep_t_kind(__VA_ARGS__, rep_t3, rep_t2, rep_t1)(__VA_ARGS__)
#define rep_t_r(...) \
    rep_t_kind(__VA_ARGS__, rep_t_r3, rep_t_r2, rep_t_r1)(__VA_ARGS__)

#define do_while_kind(a, b, c, ...) c
#define do_while1(cond) \
    for (bool is_first = true; is_first || (cond); is_first = false)
#define do_while2(cond, is_first) \
    for (bool is_first = true; is_first || (cond); is_first = false)
#define do_while(...) \
    do_while_kind(__VA_ARGS__, do_while2, do_while1)(__VA_ARGS__)

#ifdef ATCODER_MODINT_HPP
template <int M> istream &operator>>(istream &is, static_modint<M> &x) {
    ll val;
    is >> val;
    x = val;
    return is;
}
template <int M> ostream &operator<<(ostream &os, const static_modint<M> &x) {
    os << x.val();
    return os;
}

template <int id> istream &operator>>(istream &is, dynamic_modint<id> &x) {
    ll val;
    is >> val;
    x = val;
    return is;
}
template <int id>
ostream &operator<<(ostream &os, const dynamic_modint<id> &x) {
    os << x.val();
    return os;
}
#endif

inline int slot_index() {
    static int idx = ios_base::xalloc();
    return idx;
}
struct separator {
    string s;
};
inline separator sep(string s) { return {std::move(s)}; }
inline void cleanup(ios_base::event ev, ios_base &ios, int idx) {
    void *&slot = ios.pword(idx);
    if (ev == ios_base::erase_event) {
        delete static_cast<string *>(slot);
        slot = nullptr;
    } else if (ev == ios_base::copyfmt_event) {
        if (auto *p = static_cast<string *>(slot); p) {
            slot = new string(*p);
        }
    }
}
inline ostream &operator<<(ostream &os, const separator &m) {
    void *&slot = os.pword(slot_index());
    if (!slot) {
        slot = new string(m.s);
        os.register_callback(&cleanup, slot_index());
    } else {
        *static_cast<string *>(slot) = m.s;
    }
    return os;
}
inline const char *current_sep(ios_base &ios) {
    if (auto p = static_cast<string *>(ios.pword(slot_index())); p) {
        return p->c_str();
    }
    return " ";
}

template <class T>
concept char_range =
    ranges::input_range<T> && same_as<ranges::range_value_t<T>, char>;
template <class T>
concept nonstring_range =
    ranges::input_range<T> &&
    !is_convertible_v<remove_cvref_t<T>, string_view> && !char_range<T>;
template <class R>
concept writable_lvalue_range =
    is_lvalue_reference_v<ranges::range_reference_t<R>> &&
    !is_const_v<remove_reference_t<ranges::range_reference_t<R>>>;
template <class R>
concept proxy_writable_range =
    !is_lvalue_reference_v<ranges::range_reference_t<R>> &&
    !same_as<remove_cvref_t<ranges::range_reference_t<R>>,
             ranges::range_value_t<R>> &&
    default_initializable<ranges::range_value_t<R>> &&
    requires(ranges::range_reference_t<R> e, ranges::range_value_t<R> v) {
        e = std::move(v);
    };
template <class R>
concept inputtable_nonstring_range =
    nonstring_range<R> && (writable_lvalue_range<R> || proxy_writable_range<R>);

namespace io_detail {
template <class T>
concept tuple_like = requires { typename tuple_size<remove_cvref_t<T>>::type; };

template <class T> void read(istream &is, T &x);
template <class T> void write(ostream &os, T &&x);

template <class Tuple, class F> void for_each_tuple_element(Tuple &&t, F &&f) {
    [&]<size_t... I>(index_sequence<I...>) {
        using std::get;
        (f(get<I>(std::forward<Tuple>(t))), ...);
    }(make_index_sequence<tuple_size_v<remove_cvref_t<Tuple>>>{});
}

template <class T> void read(istream &is, T &x) {
    if constexpr (inputtable_nonstring_range<T>) {
        for (auto &&e : x) {
            if constexpr (writable_lvalue_range<T>) {
                read(is, e);
            } else {
                ranges::range_value_t<T> v{};
                read(is, v);
                e = std::move(v);
            }
        }
    } else if constexpr (tuple_like<T>) {
        for_each_tuple_element(x, [&](auto &e) { read(is, e); });
    } else {
        is >> x;
    }
}

template <class T> void write(ostream &os, T &&x) {
    if constexpr (nonstring_range<T>) {
        bool is_first = true;
        for (auto &&e : x) {
            if (is_first) {
                is_first = false;
            } else {
                os << current_sep(os);
            }
            write(os, std::forward<decltype(e)>(e));
        }
    } else if constexpr (tuple_like<T>) {
        bool is_first = true;
        for_each_tuple_element(std::forward<T>(x), [&](auto &&e) {
            if (is_first) {
                is_first = false;
            } else {
                os << current_sep(os);
            }
            write(os, std::forward<decltype(e)>(e));
        });
    } else {
        os << std::forward<T>(x);
    }
}
} // namespace io_detail

template <class T1, class T2>
istream &operator>>(istream &is, pair<T1, T2> &p) {
    io_detail::read(is, p);
    return is;
}
template <class T1, class T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &p) {
    io_detail::write(os, p);
    return os;
}

template <class... Ts> istream &operator>>(istream &is, tuple<Ts...> &t) {
    io_detail::read(is, t);
    return is;
}
template <class... Ts> ostream &operator<<(ostream &os, const tuple<Ts...> &t) {
    io_detail::write(os, t);
    return os;
}

template <inputtable_nonstring_range T> istream &operator>>(istream &is, T &r) {
    io_detail::read(is, r);
    return is;
}
template <nonstring_range T> ostream &operator<<(ostream &os, T &&r) {
    io_detail::write(os, std::forward<T>(r));
    return os;
}

namespace incdec_detail {
template <class> inline constexpr bool always_false_v = false;

template <class T>
concept pre_incrementable = requires(T &x) { ++x; };
template <class T>
concept pre_decrementable = requires(T &x) { --x; };
template <class T>
concept tuple_like = requires { typename tuple_size<remove_cvref_t<T>>::type; };

template <class R>
concept mutable_lvalue_range =
    ranges::input_range<R> &&
    is_lvalue_reference_v<ranges::range_reference_t<R>> &&
    !is_const_v<remove_reference_t<ranges::range_reference_t<R>>>;
template <class R>
concept mutable_proxy_range =
    ranges::input_range<R> &&
    !is_lvalue_reference_v<ranges::range_reference_t<R>> &&
    !same_as<remove_cvref_t<ranges::range_reference_t<R>>,
             ranges::range_value_t<R>> &&
    constructible_from<ranges::range_value_t<R>,
                       ranges::range_reference_t<R>> &&
    requires(ranges::range_reference_t<R> e, ranges::range_value_t<R> v) {
        e = std::move(v);
    };

template <class T> void increment_impl(T &x);
template <class T> void decrement_impl(T &x);

template <class Tuple, class F> void for_each_tuple_element(Tuple &t, F &&f) {
    [&]<size_t... I>(index_sequence<I...>) {
        using std::get;
        (f(get<I>(t)), ...);
    }(make_index_sequence<tuple_size_v<remove_cvref_t<Tuple>>>{});
}

template <class T> void increment_impl(T &x) {
    if constexpr (mutable_lvalue_range<T>) {
        for (auto &&e : x) {
            increment_impl(e);
        }
    } else if constexpr (mutable_proxy_range<T>) {
        for (auto &&e : x) {
            ranges::range_value_t<T> v(e);
            increment_impl(v);
            e = std::move(v);
        }
    } else if constexpr (ranges::input_range<T>) {
        static_assert(always_false_v<T>);
    } else if constexpr (tuple_like<T>) {
        for_each_tuple_element(x, [](auto &e) { increment_impl(e); });
    } else if constexpr (pre_incrementable<T>) {
        ++x;
    } else {
        static_assert(always_false_v<T>);
    }
}

template <class T> void decrement_impl(T &x) {
    if constexpr (mutable_lvalue_range<T>) {
        for (auto &&e : x) {
            decrement_impl(e);
        }
    } else if constexpr (mutable_proxy_range<T>) {
        for (auto &&e : x) {
            ranges::range_value_t<T> v(e);
            decrement_impl(v);
            e = std::move(v);
        }
    } else if constexpr (ranges::input_range<T>) {
        static_assert(always_false_v<T>);
    } else if constexpr (tuple_like<T>) {
        for_each_tuple_element(x, [](auto &e) { decrement_impl(e); });
    } else if constexpr (pre_decrementable<T>) {
        --x;
    } else {
        static_assert(always_false_v<T>);
    }
}
} // namespace incdec_detail

template <class T> void increment(T &x) { incdec_detail::increment_impl(x); }
template <class T> void decrement(T &x) { incdec_detail::decrement_impl(x); }

template <class... Ts> void in(Ts &...args) { (cin >> ... >> args); }
template <class... Ts> void in_z(Ts &...args) {
    in(args...);
    (decrement(args), ...);
}

namespace input_detail {
template <class Tuple> void read(Tuple &t) {
    apply(
        [](auto &...xs) {
            if constexpr (sizeof...(xs) > 0) {
                in(xs...);
            }
        },
        t);
}
template <class Tuple> void read_z(Tuple &t) {
    apply(
        [](auto &...xs) {
            if constexpr (sizeof...(xs) > 0) {
                in_z(xs...);
            }
        },
        t);
}

template <class T, size_t> using repeat_t = T;
template <class T, size_t... Is> auto input_impl(index_sequence<Is...>) {
    tuple<repeat_t<T, Is>...> t;
    read(t);
    return t;
}
template <class T, size_t... Is> auto input_z_impl(index_sequence<Is...>) {
    tuple<repeat_t<T, Is>...> t;
    read_z(t);
    return t;
}
} // namespace input_detail

template <class... Ts> auto input() {
    tuple<Ts...> t;
    in(t);
    return t;
}
template <class... Ts> auto input_z() {
    tuple<Ts...> t;
    in_z(t);
    return t;
}

template <class T, size_t N> auto input() {
    return input_detail::input_impl<T>(make_index_sequence<N>{});
}
template <class T, size_t N> auto input_z() {
    return input_detail::input_z_impl<T>(make_index_sequence<N>{});
}

template <bool do_flush = false, class Hd, class... Tl>
void out(const Hd &hd, const Tl &...tl) {
    cout << hd;
    if constexpr (sizeof...(Tl)) {
        (cout << ... << (cout << current_sep(cout), tl));
    }
#ifdef ONLINE_JUDGE
    cout << "\n";
    if constexpr (do_flush) {
        cout << flush;
    }
#else
    cout << endl;
#endif
}

template <class... Ts> void out_and_flush(const Ts &...args) {
    out<true>(args...);
}

template <class Hd, class... Tl> void err(const Hd &hd, const Tl &...tl) {
#ifndef ONLINE_JUDGE
    cerr << hd;
    if constexpr (sizeof...(Tl)) {
        (cerr << ... << (cerr << current_sep(cerr), tl));
    }
    cerr << "\n";
#endif
}

template <bool do_flush = false, class It1, class It2>
void out2(It1 first, It2 last) {
    for (; first != last; ++first) {
        out<do_flush>(*first);
    }
}
template <bool do_flush = false, class R> void out2(R &&range) {
    out2<do_flush>(begin(range), end(range));
}

template <class It1, class It2> void out2_and_flush(It1 first, It2 last) {
    out2<true>(first, last);
}
template <class R> void out2_and_flush(R &&range) { out2<true>(range); }

template <class It1, class It2> void err2(It1 first, It2 last) {
#ifndef ONLINE_JUDGE
    for (; first != last; ++first) {
        err(*first);
    }
#endif
}
template <class R> void err2(R &&range) {
#ifndef ONLINE_JUDGE
    err2(begin(range), end(range));
#endif
}

auto &change_out_sep(string s = string()) { return cout << sep(s); }
auto &change_err_sep(string s = string()) { return cerr << sep(s); }
void change_seps(string s = string()) {
    change_out_sep(s);
    change_err_sep(s);
}

constexpr array<int, 2> dx_2{1, 0}, dy_2{0, 1};
constexpr array<int, 4> dx{1, 0, -1, 0}, dy{0, 1, 0, -1};
constexpr array<int, 8> dx_8{1, 1, 0, -1, -1, -1, 0, 1},
    dy_8{0, 1, 1, 1, 0, -1, -1, -1};

namespace dir_detail {
template <size_t N>
constexpr auto zip(const array<int, N> &xs, const array<int, N> &ys) {
    array<pair<int, int>, N> res{};
    for (size_t i = 0; i < N; ++i) {
        res[i] = {xs[i], ys[i]};
    }
    return res;
}
}; // namespace dir_detail

constexpr auto dxdy_2 = dir_detail::zip(dx_2, dy_2);
constexpr auto dxdy = dir_detail::zip(dx, dy);
constexpr auto dxdy_8 = dir_detail::zip(dx_8, dy_8);

#define dir_2(dx_, dy_) for (auto [dx_, dy_] : dxdy_2)
#define dir(dx_, dy_) for (auto [dx_, dy_] : dxdy)
#define dir_8(dx_, dy_) for (auto [dx_, dy_] : dxdy_8)

#define all(v) (v).begin(), (v).end()
#define all_r(v) (v).rbegin(), (v).rend()
#define iter(v, l, r) ((v).begin() + l), ((v).begin() + r)

template <class T> void dedup(T &v) { v.erase(unique(all(v)), v.end()); }
template <class T> void sort_and_dedup(T &v) {
    sort(all(v));
    v.erase(unique(all(v)), v.end());
}

constexpr string_view yes() { return "Yes"; }
constexpr string_view no() { return "No"; }
constexpr string_view yn(bool cond) {
    if (cond) {
        return yes();
    } else {
        return no();
    }
}
string yn(bool cond, const string &yes_str, const string &no_str) {
    if (cond) {
        return yes_str;
    } else {
        return no_str;
    }
}
template <class T>
constexpr T yn(bool cond, const T &yes_val, const T &no_val) {
    if (cond) {
        return yes_val;
    } else {
        return no_val;
    }
}

template <class T1, class T2> bool chmin(T1 &l, const T2 &r) {
    if (r < l) {
        l = r;
        return true;
    }
    return false;
}
template <class T1, class T2> bool chmax(T1 &l, const T2 &r) {
    if (r > l) {
        l = r;
        return true;
    }
    return false;
}

template <class T>
using sum_type_t = typename conditional_t<is_integral_v<T>, common_type<T, ll>,
                                          type_identity<T>>::type;
template <class T, class U>
using sum_init_type_t =
    typename conditional_t<is_arithmetic_v<T> && is_arithmetic_v<U>,
                           common_type<sum_type_t<T>, U>,
                           type_identity<T>>::type;

template <class It> auto sum_of(It first, It last) {
    using T = typename iterator_traits<It>::value_type;
    return accumulate(first, last, sum_type_t<T>{});
}
template <class It, class U> auto sum_of(It first, It last, U init) {
    using T = typename iterator_traits<It>::value_type;
    using R = sum_init_type_t<T, U>;
    return accumulate(first, last, R(init));
}

template <class Hd1, class Hd2, class... Tl>
auto min_of(Hd1 hd1, Hd2 hd2, Tl... tl) {
    if constexpr (sizeof...(Tl) == 0) {
        return min(hd1, hd2);
    } else {
        return min(hd1, min_of(hd2, tl...));
    }
}
template <class Hd1, class Hd2, class... Tl>
auto max_of(Hd1 hd1, Hd2 hd2, Tl... tl) {
    if constexpr (sizeof...(Tl) == 0) {
        return max(hd1, hd2);
    } else {
        return max(hd1, max_of(hd2, tl...));
    }
}
template <class Hd1, class Hd2, class... Tl>
auto gcd_of(Hd1 hd1, Hd2 hd2, Tl... tl) {
    if constexpr (sizeof...(Tl) == 0) {
        return gcd(hd1, hd2);
    } else {
        return gcd(hd1, gcd_of(hd2, tl...));
    }
}
template <class Hd1, class Hd2, class... Tl>
auto lcm_of(Hd1 hd1, Hd2 hd2, Tl... tl) {
    if constexpr (sizeof...(Tl) == 0) {
        return lcm(hd1, hd2);
    } else {
        return lcm(hd1, lcm_of(hd2, tl...));
    }
}

namespace div_detail {
template <class T> using uncv_t = remove_cv_t<T>;

template <class T>
constexpr bool integral_non_bool_v =
    is_integral_v<uncv_t<T>> && !is_same_v<uncv_t<T>, bool>;

template <class T1, class T2>
using common_t = common_type_t<uncv_t<T1>, uncv_t<T2>>;

template <class T1, class T2>
using div_type_t =
    conditional_t<is_unsigned_v<common_t<T1, T2>> &&
                      (is_signed_v<uncv_t<T1>> || is_signed_v<uncv_t<T2>>),
                  make_signed_t<common_t<T1, T2>>, common_t<T1, T2>>;

template <class To, class From> constexpr bool fits_in_div_type(From x) {
    using F = uncv_t<From>;

    if constexpr (is_signed_v<To> && is_unsigned_v<F>) {
        using UTo = make_unsigned_t<To>;
        return x <= static_cast<UTo>(numeric_limits<To>::max());
    } else {
        return true;
    }
}
} // namespace div_detail

template <class T1, class T2>
constexpr pair<div_detail::div_type_t<T1, T2>, div_detail::div_type_t<T1, T2>>
floor_div_mod(T1 x, T2 y) {
    static_assert(div_detail::integral_non_bool_v<T1>);
    static_assert(div_detail::integral_non_bool_v<T2>);
    assert(y != 0);

    using T = div_detail::div_type_t<T1, T2>;
    assert(div_detail::fits_in_div_type<T>(x));
    assert(div_detail::fits_in_div_type<T>(y));

    T a = static_cast<T>(x), b = static_cast<T>(y);
    T q = a / b, r = a % b;

    if constexpr (is_signed_v<T>) {
        if (r != 0 && ((r < 0) != (b < 0))) {
            --q;
            r += b;
        }
    }

    return pair{q, r};
}
template <class T1, class T2>
constexpr div_detail::div_type_t<T1, T2> floor_div(T1 x, T2 y) {
    static_assert(div_detail::integral_non_bool_v<T1>);
    static_assert(div_detail::integral_non_bool_v<T2>);
    assert(y != 0);
    return floor_div_mod(x, y).first;
}
template <class T1, class T2>
constexpr div_detail::div_type_t<T1, T2> floor_mod(T1 x, T2 y) {
    static_assert(div_detail::integral_non_bool_v<T1>);
    static_assert(div_detail::integral_non_bool_v<T2>);
    assert(y != 0);
    return floor_div_mod(x, y).second;
}
template <class T1, class T2>
constexpr div_detail::div_type_t<T1, T2> ceil_div(T1 x, T2 y) {
    static_assert(div_detail::integral_non_bool_v<T1>);
    static_assert(div_detail::integral_non_bool_v<T2>);
    assert(y != 0);

    using T = div_detail::div_type_t<T1, T2>;

    auto [q, r] = floor_div_mod(x, y);
    return r == 0 ? q : static_cast<T>(q + T{1});
}

template <class T, size_t N>
auto make_vector(vector<size_t> &sizes, T const &x) {
    if constexpr (N == 1) {
        return vector(sizes[0], x);
    } else {
        size_t size = sizes[N - 1];
        sizes.pop_back();
        return vector(size, make_vector<T, N - 1>(sizes, x));
    }
}
template <class T, size_t N>
auto make_vector(size_t const (&sizes)[N], T const &x = T()) {
    vector<size_t> s(N);
    rep(i, N) { s[i] = sizes[N - i - 1]; }
    return make_vector<T, N>(s, x);
}
template <class T, size_t N> auto make_vector(vector<int> &sizes, T const &x) {
    if constexpr (N == 1) {
        return vector(sizes[0], x);
    } else {
        int size = sizes[N - 1];
        sizes.pop_back();
        return vector(size, make_vector<T, N - 1>(sizes, x));
    }
}
template <class T, size_t N>
auto make_vector(int const (&sizes)[N], T const &x = T()) {
    vector<int> s(N);
    rep(i, N) { s[i] = sizes[N - i - 1]; }
    return make_vector<T, N>(s, x);
}
template <class T, size_t Hd, size_t... Tl> auto make_array() {
    if constexpr (sizeof...(Tl) == 0) {
        return array<T, Hd>{};
    } else {
        return array<decltype(make_array<T, Tl...>()), Hd>{};
    }
}

constexpr int inf32 = 1'000'000'001;
constexpr ll inf64 = 2'000'000'000'000'000'001;

constexpr ull ten_powers[20] = {1,
                                10,
                                100,
                                1000,
                                10000,
                                100000,
                                1000000,
                                10000000,
                                100000000,
                                1000000000,
                                10000000000,
                                100000000000,
                                1000000000000,
                                10000000000000,
                                100000000000000,
                                1000000000000000,
                                10000000000000000,
                                100000000000000000,
                                1000000000000000000,
                                10000000000000000000ULL};

constexpr ull two_powers[64] = {1,
                                2,
                                4,
                                8,
                                16,
                                32,
                                64,
                                128,
                                256,
                                512,
                                1024,
                                2048,
                                4096,
                                8192,
                                16384,
                                32768,
                                65536,
                                131072,
                                262144,
                                524288,
                                1048576,
                                2097152,
                                4194304,
                                8388608,
                                16777216,
                                33554432,
                                67108864,
                                134217728,
                                268435456,
                                536870912,
                                1073741824,
                                2147483648,
                                4294967296,
                                8589934592,
                                17179869184,
                                34359738368,
                                68719476736,
                                137438953472,
                                274877906944,
                                549755813888,
                                1099511627776,
                                2199023255552,
                                4398046511104,
                                8796093022208,
                                17592186044416,
                                35184372088832,
                                70368744177664,
                                140737488355328,
                                281474976710656,
                                562949953421312,
                                1125899906842624,
                                2251799813685248,
                                4503599627370496,
                                9007199254740992,
                                18014398509481984,
                                36028797018963968,
                                72057594037927936,
                                144115188075855872,
                                288230376151711744,
                                576460752303423488,
                                1152921504606846976,
                                2305843009213693952,
                                4611686018427387904,
                                9223372036854775808ULL};

template <class T, template <class...> class Heap = priority_queue>
using min_heap = Heap<T, vector<T>, greater<>>;

template <class S, S e> constexpr S e_const() { return e; }
template <class S1, S1 e1, class S2, S2 e2>
constexpr pair<S1, S2> e_const_pair() {
    return {e1, e2};
}
template <class S> S op_min(S a, S b) { return min(a, b); }
template <class S> S op_max(S a, S b) { return max(a, b); }
template <class S> pair<S, S> op_minmax(pair<S, S> a, pair<S, S> b) {
    auto [a1, a2] = a;
    auto [b1, b2] = b;
    return {min(a1, b1), max(a2, b2)};
}
template <class S> S op_add(S a, S b) { return a + b; }
template <class S1, class S2>
pair<S1, S2> op_add_pair(pair<S1, S2> a, pair<S1, S2> b) {
    auto [a1, a2] = a;
    auto [b1, b2] = b;
    return {a1 + b1, a2 + b2};
}
template <class F1, class F2, class S> S mapping_affine(pair<F1, F2> f, S x) {
    auto [a, b] = f;
    return a * x + b;
}
template <class F1, class F2, class S>
pair<S, S> mapping_minmax_affine(pair<F1, F2> f, pair<S, S> x) {
    auto [a, b] = f;
    auto [l, r] = x;
    if (a >= 0) {
        return {a * l + b, a * r + b};
    } else {
        return {a * r + b, a * l + b};
    }
}
template <class F1, class F2, class S1, class S2>
pair<S1, S2> mapping_len_and_affine(pair<F1, F2> f, pair<S1, S2> x) {
    auto [a, b] = f;
    auto [x1, x2] = x;
    return {x1, a * x2 + b * x1};
}
template <class F1, class F2>
pair<F1, F2> composition_affine(pair<F1, F2> f, pair<F1, F2> g) {
    auto [a_f, b_f] = f;
    auto [a_g, b_g] = g;
    return {a_f * a_g, a_f * b_g + b_f};
}

template <class M, class S, S e> constexpr M mint_const() { return M(e); }
template <class M1, class S1, S1 e1, class M2, class S2, S2 e2>
constexpr pair<M1, M2> mint_pair() {
    return {M1(e1), M2(e2)};
}

#ifdef ATCODER_SEGTREE_HPP
template <class S, S e>
using segtree_min = segtree<S, op_min<S>, e_const<S, e>>;
template <class S, S e>
using segtree_max = segtree<S, op_max<S>, e_const<S, e>>;
template <class S> using segtree_add = segtree<S, op_add<S>, e_const<S, 0>>;
template <class M, class S = int>
using segtree_add_mint = segtree<M, op_add<M>, mint_const<M, S, 0>>;
#endif

#ifdef ATCODER_LAZYSEGTREE_HPP
// f の傾きが非負であることを仮定する
template <class S, S e>
using lazy_segtree_min =
    lazy_segtree<S, op_min<S>, e_const<S, e>, pair<S, S>,
                 mapping_affine<S, S, S>, composition_affine<S, S>,
                 e_const_pair<S, 1, S, 0>>;
// f の傾きが非負であることを仮定する
template <class S, S e>
using lazy_segtree_max =
    lazy_segtree<S, op_max<S>, e_const<S, e>, pair<S, S>,
                 mapping_affine<S, S, S>, composition_affine<S, S>,
                 e_const_pair<S, 1, S, 0>>;
template <class S, S e_min, S e_max>
using lazy_segtree_minmax =
    lazy_segtree<pair<S, S>, op_minmax<S>, e_const_pair<S, e_min, S, e_max>,
                 pair<S, S>, mapping_minmax_affine<S, S, S>,
                 composition_affine<S, S>, e_const_pair<S, 1, S, 0>>;
template <class S>
using lazy_segtree_add =
    lazy_segtree<pair<int, S>, op_add_pair<int, S>, e_const_pair<int, 0, S, 0>,
                 pair<S, S>, mapping_len_and_affine<S, S, int, S>,
                 composition_affine<S, S>, e_const_pair<S, 1, S, 0>>;
template <class M, class S = int>
using lazy_segtree_add_mint =
    lazy_segtree<pair<int, M>, op_add_pair<int, M>,
                 mint_pair<int, int, 0, M, S, 0>, pair<M, M>,
                 mapping_len_and_affine<M, M, int, M>, composition_affine<M, M>,
                 mint_pair<M, S, 1, M, S, 0>>;
#endif

// 一次行列多項式 det(M0 + x M1) を係数列として求める。
// 体上でのみ動作する(除算が必要)。M0, M1 は N×N。
// 多項式は a[0] + a[1]x + ... + a[N]x^N の昇順で返す。
// M1 を掃き出して I にし、det(xI + A) を特性多項式に帰着させる。
// M1 が特異でも列に x を掛ける操作を挟むことで次数 1 を保つ。
// 計算量 O(N^3)。

#include <cassert>
#include <utility>
#include <vector>

namespace determinant_of_linear_matrix_polynomial_internal {
template <class T>
bool is_square_matrix(const std::vector<std::vector<T>> &matrix) {
    const int n = static_cast<int>(matrix.size());
    for (const std::vector<T> &row : matrix) {
        if (static_cast<int>(row.size()) != n) {
            return false;
        }
    }
    return true;
}

template <class T>
void hessenberg_reduction(std::vector<std::vector<T>> &matrix) {
    const int n = static_cast<int>(matrix.size());
    for (int r = 0; r < n - 2; ++r) {
        int piv = -1;
        for (int h = r + 1; h < n; ++h) {
            if (matrix[h][r] != T()) {
                piv = h;
                break;
            }
        }
        if (piv < 0) {
            continue;
        }

        if (piv != r + 1) {
            matrix[r + 1].swap(matrix[piv]);
            for (int i = 0; i < n; ++i) {
                std::swap(matrix[i][r + 1], matrix[i][piv]);
            }
        }

        const T rinv = T(1) / matrix[r + 1][r];
        for (int i = r + 2; i < n; ++i) {
            const T coef = matrix[i][r] * rinv;
            if (coef == T()) {
                continue;
            }
            matrix[i][r] = T();
            for (int j = r + 1; j < n; ++j) {
                matrix[i][j] -= matrix[r + 1][j] * coef;
            }
            for (int j = 0; j < n; ++j) {
                matrix[j][r + 1] += matrix[j][i] * coef;
            }
        }
    }
}

template <class T>
std::vector<T> characteristic_polynomial(std::vector<std::vector<T>> matrix) {
    const int n = static_cast<int>(matrix.size());
    determinant_of_linear_matrix_polynomial_internal::hessenberg_reduction(
        matrix);

    // p[i] = det(x I_i - matrix[0..i-1][0..i-1])(係数は昇順)
    std::vector<std::vector<T>> p(n + 1);
    p[0] = {T(1)};
    for (int i = 0; i < n; ++i) {
        p[i + 1].assign(i + 2, T());

        p[i + 1][0] = T() - p[i][0] * matrix[i][i];
        for (int j = 1; j <= i; ++j) {
            p[i + 1][j] = p[i][j - 1] - p[i][j] * matrix[i][i];
        }
        p[i + 1][i + 1] = p[i][i];

        T betas = T(1);
        for (int j = i - 1; j >= 0; --j) {
            betas *= matrix[j + 1][j];
            if (betas == T()) {
                break;
            }
            if (matrix[j][i] == T()) {
                continue;
            }
            const T hb = (T() - matrix[j][i]) * betas;
            for (int k = 0; k <= j; ++k) {
                p[i + 1][k] += hb * p[j][k];
            }
        }
    }
    return p[n];
}
} // namespace determinant_of_linear_matrix_polynomial_internal

template <class T>
void hessenberg_reduction(std::vector<std::vector<T>> &matrix) {
    assert(determinant_of_linear_matrix_polynomial_internal::is_square_matrix(
        matrix));

    determinant_of_linear_matrix_polynomial_internal::hessenberg_reduction(
        matrix);
}

template <class T>
std::vector<T> characteristic_polynomial(std::vector<std::vector<T>> matrix) {
    assert(determinant_of_linear_matrix_polynomial_internal::is_square_matrix(
        matrix));

    return determinant_of_linear_matrix_polynomial_internal::
        characteristic_polynomial(std::move(matrix));
}

template <class T>
std::vector<T>
determinant_of_linear_matrix_polynomial(std::vector<std::vector<T>> M0,
                                        std::vector<std::vector<T>> M1) {
    const int n = static_cast<int>(M0.size());
    assert(static_cast<int>(M1.size()) == n);
    assert(
        determinant_of_linear_matrix_polynomial_internal::is_square_matrix(M0));
    assert(
        determinant_of_linear_matrix_polynomial_internal::is_square_matrix(M1));
    if (n == 0) {
        return {T(1)};
    }

    int multiply_by_x = 0; // 特定の列に x を掛ける操作の回数
    T det_inv = T(1);      // 1 / (det A det B)

    for (int p = 0; p < n; ++p) {
        int pivot = -1;
        for (int row = p; row < n; ++row) {
            if (M1[row][p] != T()) {
                pivot = row;
                break;
            }
        }

        if (pivot < 0) {
            ++multiply_by_x;
            if (multiply_by_x > n) {
                return std::vector<T>(n + 1, T());
            }

            // x^2 の項を発生させないため、M1[0..p-1][p] を先に消す(列基本変形)。
            for (int row = 0; row < p; ++row) {
                const T v = M1[row][p];
                if (v == T()) {
                    continue;
                }
                M1[row][p] = T();
                for (int i = 0; i < n; ++i) {
                    M0[i][p] -= v * M0[i][row];
                }
            }

            // M1 の p 列が 0 なので、M0 の p 列を M1 に移して列に x を掛ける。
            for (int i = 0; i < n; ++i) {
                M1[i][p] = std::move(M0[i][p]);
                M0[i][p] = T();
            }

            --p; // 同じ列をやり直す(高々 n 回)
            continue;
        }

        if (pivot != p) {
            M0[pivot].swap(M0[p]);
            M1[pivot].swap(M1[p]);
            det_inv = T() - det_inv; // *= -1
        }

        const T v = M1[p][p];
        det_inv *= v;
        const T vinv = T(1) / v;
        for (int col = 0; col < n; ++col) {
            M0[p][col] *= vinv;
        }
        M1[p][p] = T(1);
        for (int col = p + 1; col < n; ++col) {
            M1[p][col] *= vinv;
        }

        for (int row = 0; row < n; ++row) {
            if (row == p) {
                continue;
            }
            const T coef = M1[row][p];
            if (coef == T()) {
                continue;
            }
            for (int col = 0; col < n; ++col) {
                M0[row][col] -= M0[p][col] * coef;
            }
            M1[row][p] = T();
            for (int col = p + 1; col < n; ++col) {
                M1[row][col] -= M1[p][col] * coef;
            }
        }
    }

    // M1 = I なので det(x I + M0) を求める(特性多項式 det(x I - (-M0)))。
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            M0[i][j] = T() - M0[i][j];
        }
    }
    std::vector<T> poly = determinant_of_linear_matrix_polynomial_internal::
        characteristic_polynomial(std::move(M0));
    for (T &c : poly) {
        c *= det_inv;
    }

    if (multiply_by_x > 0) {
        poly.erase(poly.begin(), poly.begin() + multiply_by_x);
    }
    poly.resize(n + 1, T());
    return poly;
}

void solve() {
    ll n;
    ::in(n);
    std::vector<std::vector<mint>> m0(n, std::vector<mint>((n))),
        m1(n, std::vector<mint>((n)));
    in(m0, m1);

    out2(determinant_of_linear_matrix_polynomial(m0, m1));
}

int main(void) {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(15);
    cerr << fixed << setprecision(15);
    int t = 1;
    // ::in(t);
    while (t--) {
        solve();
    }
    return 0;
}
0