結果

問題 No.3158 Collect Stamps
ユーザー みうね
提出日時 2025-05-14 15:59:11
言語 C++23
(gcc 13.3.0 + boost 1.87.0)
結果
AC  
実行時間 6 ms / 2,000 ms
コード長 19,657 bytes
コンパイル時間 4,240 ms
コンパイル使用メモリ 330,692 KB
実行使用メモリ 7,844 KB
最終ジャッジ日時 2025-05-14 15:59:18
合計ジャッジ時間 5,726 ms
ジャッジサーバーID
(参考情報)
judge3 / judge4
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 3
other AC * 35
権限があれば一括ダウンロードができます
コンパイルメッセージ
main.cpp:287:7: warning: ‘template<class _Category, class _Tp, class _Distance, class _Pointer, class _Reference> struct std::iterator’ is deprecated [-Wdeprecated-declarations]
  287 |     : iterator<bidirectional_iterator_tag, Data, ptrdiff_t, Data*, Data&> {
      |       ^~~~~~~~
In file included from /usr/include/c++/13/bits/stl_algobase.h:65,
                 from /usr/include/c++/13/algorithm:60,
                 from /usr/include/x86_64-linux-gnu/c++/13/bits/stdc++.h:51,
                 from main.cpp:9:
/usr/include/c++/13/bits/stl_iterator_base_types.h:127:34: note: declared here
  127 |     struct _GLIBCXX17_DEPRECATED iterator
      |                                  ^~~~~~~~
main.cpp:289:9: warning: ‘template<class _Category, class _Tp, class _Distance, class _Pointer, class _Reference> struct std::iterator’ is deprecated [-Wdeprecated-declarations]
  289 |         iterator<bidirectional_iterator_tag, Data, ptrdiff_t, Data*, Data&>;
      |         ^~~~~~~~
/usr/include/c++/13/bits/stl_iterator_base_types.h:127:34: note: declared here
  127 |     struct _GLIBCXX17_DEPRECATED iterator
      |                                  ^~~~~~~~

ソースコード

diff #

#ifdef LOCAL
#define _GLIBCXX_DEBUG
#pragma GCC optimize("O0")
#else
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#endif

#include <bits/stdc++.h>
// #include <bits/extc++.h>
using namespace std;

#include <atcoder/modint>
using mint = atcoder::modint998244353;
istream& operator>>(istream& in, mint& x) {
    long long a;
    in >> a;
    x = a;
    return in;
}
ostream& operator<<(ostream& out, const mint& x) { return out << x.val(); }

using ll = long long;
using u32 = unsigned int;
using u64 = unsigned long long;
using i128 = __int128;
using u128 = unsigned __int128;
using f128 = __float128;

template <class T>
constexpr T infty = 0;
template <>
constexpr int infty<int> = 1'000'000'000;
template <>
constexpr ll infty<ll> = ll(infty<int>) * infty<int> * 2;
template <>
constexpr u32 infty<u32> = infty<int>;
template <>
constexpr u64 infty<u64> = infty<ll>;
template <>
constexpr i128 infty<i128> = i128(infty<ll>) * infty<ll>;
template <>
constexpr double infty<double> = infty<ll>;
template <>
constexpr long double infty<long double> = infty<ll>;

using pi = pair<int, int>;
using pl = pair<ll, ll>;
using vi = vector<int>;
using vl = vector<ll>;
template <class T>
using vc = vector<T>;
template <class T>
using vvc = vector<vc<T>>;
using vvi = vvc<int>;
using vvl = vvc<ll>;
template <class T>
using vvvc = vector<vvc<T>>;
template <class T>
using vvvvc = vector<vvvc<T>>;
template <class T>
using vvvvvc = vector<vvvvc<T>>;
template <class T>
using pqg = std::priority_queue<T, vector<T>, greater<T>>;
template <class T, class U>
using umap = unordered_map<T, U>;

// template <typename K>
// using tree = __gnu_pbds::tree<K, __gnu_pbds::null_type, std::less<>,
//                               __gnu_pbds::rb_tree_tag,
//                               __gnu_pbds::tree_order_statistics_node_update>;

#define vv(type, name, h, ...) \
    vector<vector<type>> name(h, vector<type>(__VA_ARGS__))
#define vvv(type, name, h, w, ...)     \
    vector<vector<vector<type>>> name( \
        h, vector<vector<type>>(w, vector<type>(__VA_ARGS__)))
#define vvvv(type, name, a, b, c, ...)         \
    vector<vector<vector<vector<type>>>> name( \
        a, vector<vector<vector<type>>>(       \
               b, vector<vector<type>>(c, vector<type>(__VA_ARGS__))))

// FOR(a) :=  for (ll _ = 0; _ < (ll)a; ++_)
// FOR(i, a) := for (ll i = 0; i < (ll)a; ++i)
// FOR(i, a, b) := for (ll i = a; i < (ll)b; ++i)
// FOR(i, a, b, c) := for (ll i = a; i < (ll)b; i += (c))
// FOR_R(a) := for (ll i = (a) - 1; i >= 0; --i)
// FOR_R(i, a) := for (ll i = (a) - 1; i >= 0; --i)
// FOR_R(i, a, b) := for (ll i = (b) - 1; i >= (ll)a; --i)
#define FOR1(a) for (ll _ = 0; _ < (ll)a; ++_)
#define FOR2(i, a) for (ll i = 0; i < (ll)a; ++i)
#define FOR3(i, a, b) for (ll i = a; i < (ll)b; ++i)
#define FOR4(i, a, b, c) for (ll i = a; i < (ll)b; i += (c))
#define FOR1_R(a) for (ll i = (a) - 1; i >= 0; --i)
#define FOR2_R(i, a) for (ll i = (a) - 1; i >= 0; --i)
#define FOR3_R(i, a, b) for (ll i = (b) - 1; i >= (ll)a; --i)
#define overload4(a, b, c, d, e, ...) e
#define overload3(a, b, c, d, ...) d
#define FOR(...) overload4(__VA_ARGS__, FOR4, FOR3, FOR2, FOR1)(__VA_ARGS__)
#define FOR_R(...) overload3(__VA_ARGS__, FOR3_R, FOR2_R, FOR1_R)(__VA_ARGS__)

#define FOR_subset(t, s) \
    for (int t = (s); t >= 0; t = (t == 0 ? -1 : (t - 1) & (s)))
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()

int popcnt(int x) { return __builtin_popcount(x); }
int popcnt(u32 x) { return __builtin_popcount(x); }
int popcnt(ll x) { return __builtin_popcountll(x); }
int popcnt(u64 x) { return __builtin_popcountll(x); }
int popcnt_mod_2(int x) { return __builtin_parity(x); }
int popcnt_mod_2(u32 x) { return __builtin_parity(x); }
int popcnt_mod_2(ll x) { return __builtin_parityll(x); }
int popcnt_mod_2(u64 x) { return __builtin_parityll(x); }
// (0, 1, 2, 3, 4) -> (-1, 0, 1, 1, 2)
int topbit(int x) { return (x == 0 ? -1 : 31 - __builtin_clz(x)); }
int topbit(u32 x) { return (x == 0 ? -1 : 31 - __builtin_clz(x)); }
int topbit(ll x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); }
int topbit(u64 x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); }
// (0, 1, 2, 3, 4) -> (-1, 0, 1, 0, 2)
int lowbit(int x) { return (x == 0 ? -1 : __builtin_ctz(x)); }
int lowbit(u32 x) { return (x == 0 ? -1 : __builtin_ctz(x)); }
int lowbit(ll x) { return (x == 0 ? -1 : __builtin_ctzll(x)); }
int lowbit(u64 x) { return (x == 0 ? -1 : __builtin_ctzll(x)); }

template <typename T>
T floor(T a, T b) {
    return a / b - (a % b && (a ^ b) < 0);
}
template <typename T>
T ceil(T x, T y) {
    return floor(x + y - 1, y);
}
template <typename T>
T bmod(T x, T y) {
    return x - y * floor(x, y);
}
template <typename T>
pair<T, T> divmod(T x, T y) {
    T q = floor(x, y);
    return {q, x - q * y};
}

template <typename T, typename U>
T POW(U x_, int n) {
    T x = x_;
    T ret = 1;
    while (n > 0) {
        if (n & 1) ret *= x;
        x *= x;
        n >>= 1;
    }
    return ret;
}

template <typename T, typename U>
T SUM(const vector<U>& A) {
    T sm = 0;
    for (auto&& a : A) sm += a;
    return sm;
}

#define LB(c, x) distance((c).begin(), lower_bound(all(c), (x)))
#define UB(c, x) distance((c).begin(), upper_bound(all(c), (x)))
#define UNIQUE(x) \
    sort(all(x)), x.erase(unique(all(x)), x.end()), x.shrink_to_fit()

template <class T, class S>
inline bool chmax(T& a, const S& b) {
    return (a < b ? a = b, 1 : 0);
}
template <class T, class S>
inline bool chmin(T& a, const S& b) {
    return (a > b ? a = b, 1 : 0);
}

// ? は -1
vc<int> s_to_vi(const string& S, char first_char) {
    vc<int> A(S.size());
    FOR(i, S.size()) { A[i] = (S[i] != '?' ? S[i] - first_char : -1); }
    return A;
}

template <typename T, typename U>
vector<T> cumsum(vector<U>& A, int off = 1) {
    int N = A.size();
    vector<T> B(N + 1);
    FOR(i, N) { B[i + 1] = B[i] + A[i]; }
    if (off == 0) B.erase(B.begin());
    return B;
}

template <typename T>
vector<int> argsort(const vector<T>& A) {
    vector<int> ids(A.size());
    iota(all(ids), 0);
    sort(all(ids),
         [&](int i, int j) { return (A[i] == A[j] ? i < j : A[i] < A[j]); });
    return ids;
}

// A[I[0]], A[I[1]], ...
template <typename T>
vc<T> rearrange(const vc<T>& A, const vc<int>& I) {
    vc<T> B(I.size());
    FOR(i, I.size()) B[i] = A[I[i]];
    return B;
}

template <class... T>
constexpr auto min(T... a) {
    return min(initializer_list<common_type_t<T...>>{a...});
}
template <class... T>
constexpr auto max(T... a) {
    return max(initializer_list<common_type_t<T...>>{a...});
}

void print() { cout << '\n'; }
template <class T>
void print(const T& a) {
    cout << a << '\n';
}
template <class T, class... Ts>
void print(const T& a, const Ts&... b) {
    cout << a;
    (cout << ... << (cout << ' ', b));
    cout << '\n';
}
template <class T>
void print(vector<T>& a) {
    for (int i = 0; i < (int)a.size(); ++i) {
        cout << a[i] << " \n"[i == (int)a.size() - 1];
    }
}
template <class T>
void print(vector<T>&& a) {
    for (int i = 0; i < (int)a.size(); ++i) {
        cout << a[i] << " \n"[i == (int)a.size() - 1];
    }
}
template <class T>
void print(vector<vector<T>>& a) {
    for (int i = 0; i < (int)a.size(); ++i) {
        for (int j = 0; j < (int)a[i].size(); ++j) {
            cout << a[i][j] << " \n"[j == (int)a[i].size() - 1];
        }
    }
}
template <class T>
void print(vector<vector<T>>&& a) {
    for (int i = 0; i < (int)a.size(); ++i) {
        for (int j = 0; j < (int)a[i].size(); ++j) {
            cout << a[i][j] << " \n"[j == (int)a[i].size() - 1];
        }
    }
}
void YESNO(bool b) { cout << (b ? "YES" : "NO") << endl; }
void YesNo(bool b) { cout << (b ? "Yes" : "No") << endl; }

#ifdef LOCAL
// https://zenn.dev/sassan/articles/19db660e4da0a4
#include "/Library/cpp-dump/dump.hpp"
#define dump(...) cpp_dump(__VA_ARGS__)
CPP_DUMP_DEFINE_EXPORT_OBJECT(mint, val());
#else
#define dump(...)
#define CPP_DUMP_SET_OPTION(...)
#define CPP_DUMP_DEFINE_EXPORT_OBJECT(...)
#define CPP_DUMP_DEFINE_EXPORT_ENUM(...)
#define CPP_DUMP_DEFINE_DANGEROUS_EXPORT_OBJECT(...)
#endif

//----------------------------------------------------------------
#include <cstdint>
using namespace std;

namespace HashMapImpl {
using u32 = uint32_t;
using u64 = uint64_t;

template <typename Key, typename Data>
struct HashMapBase;

template <typename Key, typename Data>
struct itrB
    : iterator<bidirectional_iterator_tag, Data, ptrdiff_t, Data*, Data&> {
    using base =
        iterator<bidirectional_iterator_tag, Data, ptrdiff_t, Data*, Data&>;
    using ptr = typename base::pointer;
    using ref = typename base::reference;

    u32 i;
    HashMapBase<Key, Data>* p;

    explicit constexpr itrB() : i(0), p(nullptr) {}
    explicit constexpr itrB(u32 _i, HashMapBase<Key, Data>* _p)
        : i(_i), p(_p) {}
    explicit constexpr itrB(u32 _i, const HashMapBase<Key, Data>* _p)
        : i(_i), p(const_cast<HashMapBase<Key, Data>*>(_p)) {}
    friend void swap(itrB& l, itrB& r) { swap(l.i, r.i), swap(l.p, r.p); }
    friend bool operator==(const itrB& l, const itrB& r) { return l.i == r.i; }
    friend bool operator!=(const itrB& l, const itrB& r) { return l.i != r.i; }
    const ref operator*() const {
        return const_cast<const HashMapBase<Key, Data>*>(p)->data[i];
    }
    ref operator*() { return p->data[i]; }
    ptr operator->() const { return &(p->data[i]); }

    itrB& operator++() {
        assert(i != p->cap && "itr::operator++()");
        do {
            i++;
            if (i == p->cap) break;
            if (p->occupied_flag[i] && !p->deleted_flag[i]) break;
        } while (true);
        return (*this);
    }
    itrB operator++(int) {
        itrB it(*this);
        ++(*this);
        return it;
    }
    itrB& operator--() {
        do {
            i--;
            if (p->occupied_flag[i] && !p->deleted_flag[i]) break;
            assert(i != 0 && "itr::operator--()");
        } while (true);
        return (*this);
    }
    itrB operator--(int) {
        itrB it(*this);
        --(*this);
        return it;
    }
};

template <typename Key, typename Data>
struct HashMapBase {
    using u32 = uint32_t;
    using u64 = uint64_t;
    using iterator = itrB<Key, Data>;
    using itr = iterator;

   protected:
    template <typename K>
    inline u64 randomized(const K& key) const {
        return u64(key) ^ r;
    }

    template <typename K,
              enable_if_t<is_same<K, Key>::value, nullptr_t> = nullptr,
              enable_if_t<is_integral<K>::value, nullptr_t> = nullptr>
    inline u32 inner_hash(const K& key) const {
        return (randomized(key) * 11995408973635179863ULL) >> shift;
    }
    template <typename K,
              enable_if_t<is_same<K, Key>::value, nullptr_t> = nullptr,
              enable_if_t<is_integral<decltype(K::first)>::value, nullptr_t> =
                  nullptr,
              enable_if_t<is_integral<decltype(K::second)>::value, nullptr_t> =
                  nullptr>
    inline u32 inner_hash(const K& key) const {
        u64 a = randomized(key.first), b = randomized(key.second);
        a *= 11995408973635179863ULL;
        b *= 10150724397891781847ULL;
        return (a + b) >> shift;
    }
    template <
        typename K, enable_if_t<is_same<K, Key>::value, nullptr_t> = nullptr,
        enable_if_t<is_integral<typename K::value_type>::value, nullptr_t> =
            nullptr>
    inline u32 inner_hash(const K& key) const {
        static constexpr u64 mod = (1LL << 61) - 1;
        static constexpr u64 base = 950699498548472943ULL;
        u64 res = 0;
        for (auto& elem : key) {
            __uint128_t x = __uint128_t(res) * base + (randomized(elem) & mod);
            res = (x & mod) + (x >> 61);
        }
        __uint128_t x = __uint128_t(res) * base;
        res = (x & mod) + (x >> 61);
        if (res >= mod) res -= mod;
        return res >> (shift - 3);
    }

    template <typename D = Data,
              enable_if_t<is_same<D, Key>::value, nullptr_t> = nullptr>
    inline u32 hash(const D& dat) const {
        return inner_hash(dat);
    }
    template <typename D = Data,
              enable_if_t<is_same<decltype(D::first), Key>::value, nullptr_t> =
                  nullptr>
    inline u32 hash(const D& dat) const {
        return inner_hash(dat.first);
    }

    template <typename D = Data,
              enable_if_t<is_same<D, Key>::value, nullptr_t> = nullptr>
    inline Key data_to_key(const D& dat) const {
        return dat;
    }
    template <typename D = Data,
              enable_if_t<is_same<decltype(D::first), Key>::value, nullptr_t> =
                  nullptr>
    inline Key data_to_key(const D& dat) const {
        return dat.first;
    }

    void reallocate(u32 ncap) {
        vector<Data> ndata(ncap);
        vector<bool> nf(ncap);
        shift = 64 - __lg(ncap);
        for (u32 i = 0; i < cap; i++) {
            if (occupied_flag[i] && !deleted_flag[i]) {
                u32 h = hash(data[i]);
                while (nf[h]) h = (h + 1) & (ncap - 1);
                ndata[h] = move(data[i]);
                nf[h] = true;
            }
        }
        data.swap(ndata);
        occupied_flag.swap(nf);
        cap = ncap;
        occupied = s;
        deleted_flag.resize(cap);
        fill(std::begin(deleted_flag), std::end(deleted_flag), false);
    }

    inline bool extend_rate(u32 x) const { return x * 2 >= cap; }

    inline bool shrink_rate(u32 x) const {
        return HASHMAP_DEFAULT_SIZE < cap && x * 10 <= cap;
    }

    inline void extend() { reallocate(cap << 1); }

    inline void shrink() { reallocate(cap >> 1); }

   public:
    u32 cap, s, occupied;
    vector<Data> data;
    vector<bool> occupied_flag, deleted_flag;
    u32 shift;
    static u64 r;
    static constexpr uint32_t HASHMAP_DEFAULT_SIZE = 4;

    explicit HashMapBase()
        : cap(HASHMAP_DEFAULT_SIZE),
          s(0),
          occupied(0),
          data(cap),
          occupied_flag(cap),
          deleted_flag(cap),
          shift(64 - __lg(cap)) {}

    itr begin() const {
        u32 h = 0;
        while (h != cap) {
            if (occupied_flag[h] && !deleted_flag[h]) break;
            h++;
        }
        return itr(h, this);
    }
    itr end() const { return itr(this->cap, this); }

    friend itr begin(const HashMapBase& h) { return h.begin(); }
    friend itr end(const HashMapBase& h) { return h.end(); }

    itr find(const Key& key) const {
        u32 h = inner_hash(key);
        while (true) {
            if (occupied_flag[h] == false) return this->end();
            if (data_to_key(data[h]) == key) {
                if (deleted_flag[h] == true) return this->end();
                return itr(h, this);
            }
            h = (h + 1) & (cap - 1);
        }
    }

    bool contain(const Key& key) const { return find(key) != this->end(); }

    itr insert(const Data& d) {
        u32 h = hash(d);
        while (true) {
            if (occupied_flag[h] == false) {
                if (extend_rate(occupied + 1)) {
                    extend();
                    h = hash(d);
                    continue;
                }
                data[h] = d;
                occupied_flag[h] = true;
                ++occupied, ++s;
                return itr(h, this);
            }
            if (data_to_key(data[h]) == data_to_key(d)) {
                if (deleted_flag[h] == true) {
                    data[h] = d;
                    deleted_flag[h] = false;
                    ++s;
                }
                return itr(h, this);
            }
            h = (h + 1) & (cap - 1);
        }
    }

    // tips for speed up :
    // if return value is unnecessary, make argument_2 false.
    itr erase(itr it, bool get_next = true) {
        if (it == this->end()) return this->end();
        s--;
        if (!get_next) {
            this->deleted_flag[it.i] = true;
            if (shrink_rate(s)) shrink();
            return this->end();
        }
        itr nxt = it;
        nxt++;
        this->deleted_flag[it.i] = true;
        if (shrink_rate(s)) {
            Data d = data[nxt.i];
            shrink();
            it = find(data_to_key(d));
        }
        return nxt;
    }

    itr erase(const Key& key) { return erase(find(key)); }

    int count(const Key& key) { return find(key) == end() ? 0 : 1; }

    bool empty() const { return s == 0; }

    int size() const { return s; }

    void clear() {
        fill(std::begin(occupied_flag), std::end(occupied_flag), false);
        fill(std::begin(deleted_flag), std::end(deleted_flag), false);
        s = occupied = 0;
    }

    void reserve(int n) {
        if (n <= 0) return;
        n = 1 << min(23, __lg(n) + 2);
        if (cap < u32(n)) reallocate(n);
    }
};

template <typename Key, typename Data>
uint64_t HashMapBase<Key, Data>::r =
    chrono::duration_cast<chrono::nanoseconds>(
        chrono::high_resolution_clock::now().time_since_epoch())
        .count();

}  // namespace HashMapImpl

template <typename Key, typename Val>
struct HashMap : HashMapImpl::HashMapBase<Key, pair<Key, Val>> {
    using base = typename HashMapImpl::HashMapBase<Key, pair<Key, Val>>;
    using HashMapImpl::HashMapBase<Key, pair<Key, Val>>::HashMapBase;
    using Data = pair<Key, Val>;

    Val& operator[](const Key& k) {
        typename base::u32 h = base::inner_hash(k);
        while (true) {
            if (base::occupied_flag[h] == false) {
                if (base::extend_rate(base::occupied + 1)) {
                    base::extend();
                    h = base::hash(k);
                    continue;
                }
                base::data[h].first = k;
                base::data[h].second = Val();
                base::occupied_flag[h] = true;
                ++base::occupied, ++base::s;
                return base::data[h].second;
            }
            if (base::data[h].first == k) {
                if (base::deleted_flag[h] == true) {
                    base::data[h].second = Val();
                    base::deleted_flag[h] = false;
                    ++base::s;
                }
                return base::data[h].second;
            }
            h = (h + 1) & (base::cap - 1);
        }
    }

    typename base::itr emplace(const Key& key, const Val& val) {
        return base::insert(Data(key, val));
    }
};

void solve() {
    int N, M, K;
    cin >> N >> M >> K;
    vector<int> A(K);
    for (int i = 0; i < K; ++i) {
        cin >> A[i];
        --A[i];
    }
    vector T(N, vector<int>(N));
    for (int i = 0; i < N; ++i) {
        for (int j = 0; j < N; ++j) {
            cin >> T[i][j];
        }
    }
    HashMap<pair<int, int>, int> memo;
    auto dfs = [&](auto&& self, int msk, int v) -> int {
        if (memo.contain({msk, v})) return memo[{msk, v}];
        if (popcnt(msk) >= M) return memo[{msk, v}] = 0;
        int ans = infty<int>;
        for (int i = 0; i < N; ++i) {
            if ((msk >> i) & 1) continue;
            int nmsk = msk | (1 << i);
            chmin(ans, self(self, nmsk, i) + T[i][v]);
        }
        return memo[{msk, v}] = ans;
    };
    int ans = infty<int>;
    for (int i = 0; i < K; ++i) {
        int tmp = dfs(dfs, 1 << A[i], A[i]);
        chmin(ans, tmp);
    }
    print(ans);
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(20);
    CPP_DUMP_SET_OPTION(max_line_width, 80);
    CPP_DUMP_SET_OPTION(log_label_func, cpp_dump::log_label::filename());
    CPP_DUMP_SET_OPTION(enable_asterisk, true);
    solve();
    return 0;
}
0