algo — C++23 日本語リファレンス GitHub

test/yukicoder/0261.test.cpp

AC · 最終更新 2026-09-07 · GitHub

問題: https://yukicoder.me/problems/no/261

依存するヘッダ(2)
実装
// competitive-verifier: PROBLEM https://yukicoder.me/problems/no/261
#include <iostream>
#include <numeric>
#include <string>
#include <vector>
#include "number_theory/discrete_log.hpp"

// 置換(合成)モノイドが配置(arrangement)に作用する acted_set。
// 作用素・状態ともに長さ n の置換/配置を vector<int> で表す。
// op(a, b)[i] = a[b[i]](合成)、f(perm, arr)[i] = arr[perm[i]](作用)。
struct Permutation {
    using value_type = std::vector<int>;
    static inline int n;
    static value_type id() {
        value_type e(n);
        std::iota(e.begin(), e.end(), 0);
        return e;
    }
    static value_type op(const value_type &a, const value_type &b) {
        value_type c(n);
        for (int i = 0; i < n; ++i) c[i] = a[b[i]];
        return c;
    }
    static value_type f(const value_type &perm, const value_type &arr) {
        value_type res(n);
        for (int i = 0; i < n; ++i) res[i] = arr[perm[i]];
        return res;
    }
};

int main(void) {
    int n, k;
    std::cin >> n >> k;
    Permutation::n = n;

    // あみだくじ 1 回分を「配置のスロット入れ替え」を表す置換 base に畳み込む
    std::vector<int> base(n);
    std::iota(base.begin(), base.end(), 0);
    while (k--) {
        int x, y;
        std::cin >> x >> y;
        std::swap(base[x - 1], base[y - 1]);
    }

    // 状態(配置)を一意な文字列キーへ(値域は 1..n なので衝突しない完全キー)
    auto to_key = [](const std::vector<int> &arr) {
        std::string s(arr.size(), '\0');
        for (std::size_t i = 0; i < arr.size(); ++i) s[i] = static_cast<char>(arr[i]);
        return s;
    };

    std::vector<int> start(n);
    std::iota(start.begin(), start.end(), 1);  // 初期配置 [1, 2, ..., n]

    int q;
    std::cin >> q;
    while (q--) {
        std::vector<int> target(n);
        for (auto &e : target) std::cin >> e;
        // base を start に何回作用させれば target になるか(n >= 1)。g(100) < 2^30 より上界は 2^30 で十分。
        std::int64_t ans = discrete_log_acted<Permutation, std::vector<int>>(base, start, target, to_key, 1, 1LL << 30);
        std::cout << ans << '\n';
    }

    return 0;
}