結果

問題 No.103 素因数ゲーム リターンズ
コンテスト
ユーザー chabudaisanta
提出日時 2025-10-16 19:52:47
言語 C++23
(gcc 13.3.0 + boost 1.87.0)
結果
AC  
実行時間 2 ms / 5,000 ms
コード長 21,071 bytes
コンパイル時間 5,242 ms
コンパイル使用メモリ 306,960 KB
実行使用メモリ 7,716 KB
最終ジャッジ日時 2025-10-16 19:52:53
合計ジャッジ時間 6,361 ms
ジャッジサーバーID
(参考情報)
judge1 / judge3
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 5
other AC * 20
権限があれば一括ダウンロードができます

ソースコード

diff #

#line 2 "/home/chabudaisanta/lib/gwen/src/gwen/my_template.hpp"
#ifdef LOCAL
#define _GLIBCXX_DEBUG
#endif
#include <algorithm>
#include <array>
#include <bit>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <climits>
#include <cmath>
#include <compare>
#include <concepts>
#include <deque>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <locale>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <ranges>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

#line 2 "/home/chabudaisanta/lib/gwen/src/gwen/dump.hpp"

#line 17 "/home/chabudaisanta/lib/gwen/src/gwen/dump.hpp"

#line 2 "/home/chabudaisanta/lib/gwen/src/gwen/types.hpp"

#include <cstdint>

namespace gwen {

using i32 = int32_t;
using i64 = int64_t;
using i128 = __int128_t;
using u32 = uint32_t;
using u64 = uint64_t;
using u128 = __uint128_t;

}  // namespace gwen
#line 19 "/home/chabudaisanta/lib/gwen/src/gwen/dump.hpp"

namespace gwen {

//-------------------------
// standard types
//-------------------------
constexpr inline std::string to_str() { return ""; }
constexpr inline std::string to_str(bool b) { return b ? "true" : "false"; }
constexpr inline std::string to_str(char c) { return std::string{c}; }
constexpr inline std::string to_str(const char* cs) { return std::string{cs}; }
constexpr inline std::string to_str(const std::string& str) { return str; }
constexpr inline std::string to_str(std::nullptr_t) { return "nullptr"; }
constexpr inline std::string to_str(u128 x) {
    if (x == 0) return "0";
    std::string ret;
    while (x) {
        ret.push_back(static_cast<char>('0' + (x % 10)));
        x /= 10;
    }
    std::reverse(ret.begin(), ret.end());
    return ret;
}
constexpr inline std::string to_str(i128 x) {
    if (x < 0) return std::string{'-'} + to_str(static_cast<u128>(-x));
    return to_str(static_cast<u128>(x));
}

template <std::integral T> std::string to_str(T x) { return std::to_string(x); }
template <std::floating_point T> std::string to_str(T f) {
    return std::to_string(f);
}

//-------------------------
// prototype
//-------------------------

// pair / tuple
template <typename T1, typename T2>
std::string to_str(const std::pair<T1, T2>& p);
template <typename... Ts> std::string to_str(const std::tuple<Ts...>& t);

// input iterator helper
template <std::input_iterator Iterator>
std::string to_str(Iterator begin,
                   Iterator end,
                   const std::string& partition = ", ",
                   char pb = '\0',
                   char pe = '\0');

// sequence containers
template <typename T> std::string to_str(const std::vector<T>& sc);
template <typename T, std::size_t N>
std::string to_str(const std::array<T, N>& sc);
template <typename T> std::string to_str(const std::deque<T>& sc);
template <typename T, std::size_t N> std::string to_str(const T (&sc)[N]);

// set containers
template <typename T> std::string to_str(const std::set<T>& se);
template <typename T> std::string to_str(const std::multiset<T>& se);
template <typename T> std::string to_str(const std::unordered_set<T>& se);
template <typename T> std::string to_str(const std::unordered_multiset<T>& se);

// map containers
template <typename K, typename V> std::string to_str(const std::map<K, V>& mp);
template <typename K, typename V>
std::string to_str(const std::multimap<K, V>& mp);
template <typename K, typename V>
std::string to_str(const std::unordered_map<K, V>& mp);
template <typename K, typename V>
std::string to_str(const std::unordered_multimap<K, V>& mp);
template <std::input_iterator Iterator>
std::string to_str_map_helper(Iterator begin, Iterator end);

// user-defined
template <typename T>
    requires requires(const T& t) { gwen::to_str(t.val()); }
std::string to_str(const T& t);
template <typename T>
    requires requires(const T& t) { gwen::to_str(t.dump()); }
std::string to_str(const T& t);

//-------------------------
// implementation
//-------------------------

// pair / tuple
template <typename T1, typename T2>
std::string to_str(const std::pair<T1, T2>& p) {
    return std::string{'('} + to_str(p.first) + ", " + to_str(p.second) + ')';
}
template <typename... Ts> std::string to_str(const std::tuple<Ts...>& t) {
    std::string ret{'('};
    bool first = true;
    std::apply(
        [&](const auto&... args) {
            ((ret += (first ? "" : ", "), ret += gwen::to_str(args),
              first = false),
             ...);
        },
        t);
    return ret + ')';
}

template <typename... Args>
inline std::string to_str_variadic(const Args&... args) {
    std::string ret;
    std::size_t index = 0;

    auto process_one = [&](const auto& arg) {
        if (index++ > 0) {
            ret += ", ";
        }

        if constexpr (requires { gwen::to_str(arg); }) {
            ret += gwen::to_str(arg);
        }
        else {
            ret += "[?]";
        }
    };

    (process_one(args), ...);

    return ret;
}

// input iterator helper
template <std::input_iterator Iterator>
std::string to_str(Iterator begin,
                   Iterator end,
                   const std::string& partition,
                   char pb,
                   char pe) {
    std::string ret;
    if (pb) ret += pb;
    for (auto it = begin; it != end; ++it) {
        if (it != begin) ret += partition;
        ret += to_str(*it);
    }
    if (pe) ret += pe;
    return ret;
}

// sequence containers
template <typename T> std::string to_str(const std::vector<T>& sc) {
    return to_str(sc.begin(), sc.end(), ", ", '[', ']');
}
template <typename T, std::size_t N>
std::string to_str(const std::array<T, N>& sc) {
    return to_str(sc.begin(), sc.end(), ", ", '[', ']');
}
template <typename T> std::string to_str(const std::deque<T>& sc) {
    return to_str(sc.begin(), sc.end(), ", ", '[', ']');
}
template <typename T, std::size_t N> std::string to_str(const T (&sc)[N]) {
    return to_str(sc.begin(), sc.end(), ", ", '[', ']');
}

// set containers
template <typename T> std::string to_str(const std::set<T>& se) {
    return to_str(se.begin(), se.end(), ", ", '{', '}');
}
template <typename T> std::string to_str(const std::multiset<T>& se) {
    return to_str(se.begin(), se.end(), ", ", '{', '}');
}
template <typename T> std::string to_str(const std::unordered_set<T>& se) {
    return to_str(se.begin(), se.end(), ", ", '{', '}');
}
template <typename T> std::string to_str(const std::unordered_multiset<T>& se) {
    return to_str(se.begin(), se.end(), ", ", '{', '}');
}

// map containers
template <typename K, typename V> std::string to_str(const std::map<K, V>& mp) {
    return to_str_map_helper(mp.begin(), mp.end());
}
template <typename K, typename V>
std::string to_str(const std::multimap<K, V>& mp) {
    return to_str_map_helper(mp.begin(), mp.end());
}
template <typename K, typename V>
std::string to_str(const std::unordered_map<K, V>& mp) {
    return to_str_map_helper(mp.begin(), mp.end());
}
template <typename K, typename V>
std::string to_str(const std::unordered_multimap<K, V>& mp) {
    return to_str_map_helper(mp.begin(), mp.end());
}
template <std::input_iterator Iterator>
std::string to_str_map_helper(Iterator begin, Iterator end) {
    std::string ret{'{'};
    for (auto it = begin; it != end; ++it) {
        if (it != begin) ret += ", ";
        ret += '(' + to_str(it->first) + ": " + to_str(it->second) + ')';
    }
    ret += '}';
    return ret;
}

// user-defined
template <typename T>
    requires requires(const T& t) { gwen::to_str(t.val()); }
std::string to_str(const T& t) {
    return gwen::to_str(t.val());
}
template <typename T>
    requires requires(const T& t) { gwen::to_str(t.dump()); }
std::string to_str(const T& t) {
    return gwen::to_str(t.dump());
}

}  // namespace gwen

#ifdef LOCAL
#define DEBUG(...)                                                          \
    std::cerr << #__VA_ARGS__ << ": " << gwen::to_str_variadic(__VA_ARGS__) \
              << '\n'
#define DUMP(...)                                                           \
    std::cerr << #__VA_ARGS__ << ": " << gwen::to_str_variadic(__VA_ARGS__) \
              << '\n'
#else
#define DEBUG(...) void(0)
#define DUMP(...)  void(0)
#endif

// std::string += std::string は、atcoder環境なら線形時間でやってくれそう
// https://atcoder.jp/contests/abc379/submissions/69207872
#line 37 "/home/chabudaisanta/lib/gwen/src/gwen/my_template.hpp"
using gwen::i128;
using gwen::i32;
using gwen::i64;
using gwen::u128;
using gwen::u32;
using gwen::u64;
using ll = long long;
using ull = unsigned long long;

#define rep(i, l, r)  for (int i = (int)(l); i < (int)(r); ++i)
#define rp(i, n)      for (int i = 0; i < (int)(n); ++i)
#define rrep(i, l, r) for (int i = (int)(r) - 1; i >= (int)(l); --i)
#define all(a)        a.begin(), a.end()
#define rall(a)       a.rbegin(), a.rend()

#ifdef LOCAL
#define BAR   std::cerr << "----------------------------------------------\n"
#define S_BAR std::cerr << "------------------\n"
#else
#define BAR   void(0)
#define S_BAR void(0)
#endif

constexpr std::pair<int, int> mv[] = {{0, 1},   {1, 0},  {0, -1},
                                      {-1, 0},  {1, 1},  {1, -1},
                                      {-1, -1}, {-1, 1}, {0, 0}};
constexpr int dw[] = {0, 0, -1, 1, -1, -1, 1, 1, 0};
constexpr int dh[] = {-1, 1, 0, 0, -1, 1, -1, 1, 0};
constexpr int mod998 = 998244353, mod107 = 1000000007, mod109 = 1000000009,
              mod31 = 2147483647;
constexpr ll mod61 = (1LL << 61) - 1;
constexpr int iINF = (1 << 30) + 1;
constexpr ll liINF = (1LL << 60) + 1;
constexpr char EL = '\n', SPA = ' ';

std::pair<int, int> mv_to(int hi, int wi, int dir) {
    assert(0 <= dir && dir < 9);
    return std::make_pair(hi + dh[dir], wi + dw[dir]);
}

template <typename T1, typename T2> inline bool chmax(T1& a, T2 b) {
    return (a < b ? a = b, true : false);
}
template <typename T1, typename T2> inline bool chmin(T1& a, T2 b) {
    return (a > b ? a = b, true : false);
}

template <std::integral T> inline bool isIn(T x, T l, T r) {
    return (l <= x) && (x < r);
}
template <std::integral T> inline bool isOut(T x, T l, T r) {
    return (x < l) || (r <= x);
}

template <typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& vec) {
    for (auto it = vec.begin(); it != vec.end(); it++)
        os << *it << (it == prev(vec.end()) ? "" : " ");
    return os;
}
template <typename T>
std::istream& operator>>(std::istream& is, std::vector<T>& vec) {
    for (T& e : vec) is >> e;
    return is;
}
void yon(bool b) { std::cout << (b ? "Yes\n" : "No\n"); }

template <typename T>
std::vector<int> idxsort(const std::vector<T>& vec, bool rev = false) {
    std::vector<int> ret(vec.size());
    std::iota(ret.begin(), ret.end(), 0);
    sort(ret.begin(), ret.end(), [&vec, &rev](int a, int b) {
        return (rev ? vec[a] > vec[b] : vec[a] < vec[b]);
    });
    return ret;
}
template <std::integral T> T ceil_div(T x, T y) {
    assert(y != 0);
    T d = x / y;
    return d * y == x ? d : d + ((x > 0) ^ (y < 0));
}
template <std::integral T> T floor_div(T x, T y) {
    assert(y != 0);
    T d = x / y;
    return d * y == x ? d : d - ((x < 0) ^ (y < 0));
}
template <std::integral T> T out_div(T x, T y) {
    assert(y != 0);
    T d = x / y;
    return d * y == x ? d : ((x > 0) == (y > 0)) ? d + 1 : d - 1;
}
// https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3605r0.pdf
template <std::unsigned_integral T> constexpr T isqrt(const T n) noexcept {
    if (n <= T{1}) return n;
    T i_current{0}, i_next{T(T{1} << ((std::bit_width(T(n - 1)) + 1) >> 1))};
    do {
        i_current = i_next;
        i_next = T((i_current + n / i_current) >> 1);
    } while (i_next < i_current);
    return i_current;
}

template <typename T> constexpr T sq(T x) { return x * x; }
template <std::integral T> constexpr T choose2(T x) { return x * (x - 1) / 2; }
template <std::integral T1, std::integral T2>
constexpr T1 getBit(T1 bit, T2 i) {
    return bit & (static_cast<T1>(1) << i);
}
template <std::integral T1, std::integral T2>
constexpr T1 setBit(T1 bit, T2 i) {
    return bit | (static_cast<T1>(1) << i);
}
template <std::integral T1, std::integral T2>
constexpr T1 clearBit(T1 bit, T2 i) {
    return bit & ~(static_cast<T1>(1) << i);
}
template <std::integral T1, std::integral T2>
constexpr T1 toggleBit(T1 bit, T2 i) {
    return bit ^ (static_cast<T1>(1) << i);
}

template <typename Iterator> auto runlength(Iterator begin, Iterator end) {
    using ValueType = typename std::iterator_traits<Iterator>::value_type;
    using CountType = int;
    std::vector<std::pair<ValueType, CountType>> ret;

    for (auto it = begin; it != end; ++it) {
        if (ret.empty() || ret.back().first != *it) ret.emplace_back(*it, 0);
        ret.back().second++;
    }
    return ret;
}

#if __has_include(<atcoder/all>)
#include <atcoder/all>
using mint998 = atcoder::modint998244353;
using mint107 = atcoder::modint1000000007;
#endif
#if __has_include(<gmpxx.h>)
#include <gmpxx.h>
using gmp_int = mpz_class;
#endif
/*
#if __has_include(<Eigen/Dense>)
#include <Eigen/Dense>
#endif
*/
#line 2 "/home/chabudaisanta/lib/gwen/src/gwen/math/prime.hpp"

#line 4 "/home/chabudaisanta/lib/gwen/src/gwen/math/prime.hpp"

#line 2 "/home/chabudaisanta/lib/gwen/src/gwen/mod/modint.hpp"
// https://rsk0315.hatenablog.com/entry/2022/11/27/060616
#line 4 "/home/chabudaisanta/lib/gwen/src/gwen/mod/modint.hpp"

#line 2 "/home/chabudaisanta/lib/gwen/src/gwen/mod/mod.hpp"

#line 4 "/home/chabudaisanta/lib/gwen/src/gwen/mod/mod.hpp"

#line 6 "/home/chabudaisanta/lib/gwen/src/gwen/mod/mod.hpp"

namespace gwen {

i64 pow_mod(i64 x, i64 n, i64 m = 998244353) {
    if (x == 0) return (n ? 0 : 1);
    x %= m;
    i64 ret = 1;
    while (n) {
        if (n & 1) ret = (ret * x) % m;
        x = (x * x) % m;
        n >>= 1;
    }
    return ret;
}

i64 inv_mod(i64 a, i64 m = 998244353) {
    i64 b = m, u = 1, v = 0;
    while (b) {
        i64 t = a / b;
        a -= t * b;
        std::swap(a, b);
        u -= t * v;
        std::swap(u, v);
    }
    u %= m;
    if (u < 0) u += m;
    return u;
}

u64 inv_mod_64(u64 a, u64 m) {
    i128 s = m, t = a;
    i128 x = 0, y = 1;

    while (t) {
        i128 u = s / t;
        s -= t * u;
        x -= y * u;
        std::swap(s, t);
        std::swap(x, y);
    }
    // assert(s == 1); // gcd(a,m)が1でなければ逆元は存在しない
    return (x % m + m) % m;
}

}  // namespace gwen
#line 7 "/home/chabudaisanta/lib/gwen/src/gwen/mod/modint.hpp"

namespace gwen {

class dynamic_modint64 {
    using m64 = dynamic_modint64;
    static inline u64 n = 1;
    static inline u64 ns = 0;
    static inline u64 r2 = 0;
    static inline constexpr u64 msk = -1;

    u64 reduce_mul(u64 a, u64 b) const {
        u128 t = static_cast<u128>(a) * b;
        u128 m = (t * ns) & msk;  // maybe unnecessary mask ?
        a = (m * n + t) >> 64;    // t ← (t + mN) / R
        return a < n ? a : a - n;
    }

    u64 tr;

public:
    static void set_mod(u64 n_) {
        assert(n_ < (1ull << 62));
        assert(n_ & 1);
        n = n_;
        ns = n;
        for (int i = 0; i < 5; ++i) ns *= 2 - ns * n;
        assert(ns * n == 1);
        ns = -ns;
        r2 = -static_cast<u128>(n) % n;
    }

    dynamic_modint64() : tr(0) {}

    // need 0 <= abs(x) < RN
    template <std::unsigned_integral T>
    dynamic_modint64(T x) : tr(reduce_mul(x, r2)) {}
    template <std::signed_integral T> dynamic_modint64(T x) : tr(0) {
        if (x < 0)
            sub(m64{static_cast<u64>(-x)});
        else
            tr = reduce_mul(x, r2);
    }

    u64 val() const { return reduce_mul(tr, 1); }

    // basic operation
    m64& sub(const m64& x) {
        if (tr < x.tr) tr += n;
        tr -= x.tr;
        return *this;
    }
    m64& add(const m64& x) {
        tr += x.tr;
        if (tr >= n) tr -= n;
        return *this;
    }
    m64& mul(const m64& x) {
        tr = reduce_mul(tr, x.tr);
        return *this;
    }

    // operator overload
    m64& operator+=(const m64& x) { return add(x); }
    m64 operator+(const m64& x) const {
        m64 tmp = *this;
        tmp.add(x);
        return tmp;
    }

    m64& operator-=(const m64& x) { return sub(x); }
    m64 operator-(const m64& x) const {
        m64 tmp = *this;
        tmp.sub(x);
        return tmp;
    }

    m64& operator*=(const m64& x) { return mul(x); }
    m64 operator*(const m64& x) const {
        m64 tmp = *this;
        tmp.mul(x);
        return tmp;
    }

    // operator overload (integral)
    template <std::integral T> m64& operator+=(T x) { return add(m64(x)); }
    template <std::integral T> m64 operator+(T x) const {
        return *this + m64(x);
    }

    template <std::integral T> m64& operator-=(T x) { return sub(m64(x)); }
    template <std::integral T> m64 operator-(T x) const {
        return *this - m64(x);
    }

    template <std::integral T> m64& operator*=(T x) { return mul(m64(x)); }
    template <std::integral T> m64 operator*(T x) const {
        return *this * m64(x);
    }

    template <std::integral T> m64 pow(T x) const {
        assert(x >= 0);
        m64 ret(1);
        m64 tmp(*this);
        while (x) {
            if (x & 1) ret.mul(tmp);
            tmp.tr = reduce_mul(tmp.tr, tmp.tr);
            x >>= 1;
        }
        return ret;
    }
};

}  // namespace gwen
#line 7 "/home/chabudaisanta/lib/gwen/src/gwen/math/prime.hpp"

namespace gwen {

namespace internal {

struct prime_factorize_table {
    i32 n;
    std::vector<i32> p;  // p[i] = 0: i is prime (or 1/0)

    prime_factorize_table() : n(2), p(2, 0) {}

    void extend() {
        assert(n < (1 << 30));
        n <<= 1;
        p.resize(n, 0);
        for (int i = 2; i < n; ++i)
            if (!p[i]) {
                for (i64 j = i64(i) * i; j < n; j += i) {
                    p[j] = i;
                }
            }
    }

    // if x <= max() can factorize
    // else cannot factorize
    i32 max() const { return n - 1; }
};

}  // namespace internal

std::vector<i32> factorize(i32 x) {
    assert(0 < x && x < (1 << 30));
    static gwen::internal::prime_factorize_table table;
    while (table.max() < x) table.extend();
    std::vector<i32> ret;
    while (table.p[x] != 0) {
        // if p[x] = 0, x is prime
        ret.emplace_back(table.p[x]);
        x /= table.p[x];
    }
    if (x != 1) ret.emplace_back(x);
    return ret;
}

bool miller32(u32 n) {
    assert(n < 4759123141u);
    static u64 a[3] = {2, 7, 61};
    using mint = dynamic_modint64;
    mint::set_mod(n);
    u64 s = 0, d = n - 1;
    while (!(d & 1)) {
        ++s;
        d >>= 1;
    }
    for (int i = 0; i < 3; ++i) {
        if (n <= a[i]) return true;
        mint x{a[i]};
        x = x.pow(d);
        if (x.val() != 1u) {
            u64 t;
            for (t = 0; t < s; ++t) {
                if (x.val() == n - 1) break;
                x *= x;
            }
            if (t == s) return false;
        }
    }
    return true;
}

bool miller64(u64 n) {
    static u64 a[7] = {2, 325, 9375, 28178, 450775, 9780504, 1795265022};
    using mint = dynamic_modint64;
    mint::set_mod(n);
    u64 s = 0, d = n - 1;
    while (!(d & 1)) {
        ++s;
        d >>= 1;
    }
    for (int i = 0; i < 7; ++i) {
        if (n <= a[i]) return true;
        mint x{a[i]};
        x = x.pow(d);
        u64 t;
        if (x.val() != 1u) {
            for (t = 0; t < s; ++t) {
                if (x.val() == n - 1) break;
                x *= x;
            }
            if (t == s) return false;
        }
    }
    return true;
}

bool is_prime_small(i32 n) {
    static gwen::internal::prime_factorize_table table;
    while (table.max() < n) table.extend();
    return !table.p[n];
}

bool miller(u64 n) {
    if (n <= 1)
        return false;
    else if (n == 2)
        return true;
    else if (!(n & 1))
        return false;
    else if (n < (1u << 23))
        return is_prime_small(n);
    else if (n < 4759123141u)
        return miller32(n);
    else
        return miller64(n);
}


}  // namespace gwen
#line 3 "a.cpp"
using namespace std;

void solve() {
    i32 N; cin >> N;
    vector<i32> M(N); cin >> M;
    vector<vector<i32>> F(N);
    u32 grundy = 0;
    rp(i,N) {
        F[i] = gwen::factorize(M[i]);
        DUMP(F[i]);
        map<i32,u32> cnt;
        for(i32 f : F[i]) cnt[f]++;
        u32 g = 0;
        for(auto [k, v] : cnt) {
            g ^= v % 3;
        }
        grundy ^= g;
        DUMP(g);
    }
    cout << (grundy ? "Alice" : "Bob") << EL;
}


int main(void) {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    std::cout << std::fixed << std::setprecision(16);

    int t = 1;
    // cin >> t;
    while (t--) solve();

    std::cerr << "execution time: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000
              << "(ms)" << EL;
    return 0;
}
0