Submission #520263

#TimeUsernameProblemLanguageResultExecution timeMemory
520263KoDTrener (COCI20_trener)C++17
110 / 110
1181 ms2372 KiB
#line 1 "main.cpp" #include <bits/stdc++.h> #define ENABLE_AVX2 #line 3 "/Users/kodamankod/Desktop/CppProcon/Library/proconlib/utility/int_alias.cpp" using i32 = std::int32_t; using u32 = std::uint32_t; using i64 = std::int64_t; using u64 = std::uint64_t; using i128 = __int128_t; using u128 = __uint128_t; #line 3 "/Users/kodamankod/Desktop/CppProcon/Library/proconlib/utility/rep.cpp" class Range { struct Iter { int itr; constexpr Iter(const int pos) noexcept : itr(pos) {} constexpr void operator++() noexcept { ++itr; } constexpr bool operator!=(const Iter& other) const noexcept { return itr != other.itr; } constexpr int operator*() const noexcept { return itr; } }; const Iter first, last; public: explicit constexpr Range(const int first, const int last) noexcept : first(first), last(std::max(first, last)) {} constexpr Iter begin() const noexcept { return first; } constexpr Iter end() const noexcept { return last; } }; constexpr Range rep(const int l, const int r) noexcept { return Range(l, r); } constexpr Range rep(const int n) noexcept { return Range(0, n); } #line 5 "/Users/kodamankod/Desktop/CppProcon/Library/proconlib/random/xorshift.cpp" u64 xorshift() { static u64 state = std::chrono::system_clock::now().time_since_epoch().count(); state ^= state << 7; state ^= state >> 9; return state; } #line 4 "/Users/kodamankod/Desktop/CppProcon/Library/proconlib/random/rand_int.cpp" template <class T> T rand_int(const T& min, const T& max) { static std::default_random_engine gen(xorshift()); return std::uniform_int_distribution<T>(min, max)(gen); } #line 9 "/Users/kodamankod/Desktop/CppProcon/Library/proconlib/container/polynomial_hash.cpp" struct PolynomialHashOperations { static inline constexpr u64 MOD = ((u64)1 << 61) - 1; static constexpr u64 sum(u64 a, const u64 b) { return (a += b) >= MOD ? a - MOD : a; } static constexpr u64 difference(u64 a, const u64 b) { return (a += MOD - b) >= MOD ? a - MOD : a; } static constexpr u64 product(const u64 a, const u64 b) { u128 ret = (u128)a * b; ret = (ret >> 61) + (ret & MOD); return ret >= MOD ? ret - MOD : ret; } }; template <int ID> struct PolynomialHashBase { static inline const u64 BASE = rand_int<u64>(0, PolynomialHashOperations::MOD - 1); static u64 base_pow(const int n) { static std::vector<u64> vec; if (vec.empty()) vec = {1}; while ((int)vec.size() <= n) vec.push_back(PolynomialHashOperations::product(vec.back(), BASE)); return vec[n]; } }; template <class T, int ID = -1, std::enable_if_t<std::is_integral_v<T>>* = nullptr> class PolynomialHash { using Oper = PolynomialHashOperations; using Base = PolynomialHashBase<ID>; std::vector<u64> hash; std::vector<T> data; public: PolynomialHash() : PolynomialHash(std::vector<T>()) {} explicit PolynomialHash(const std::vector<T>& vec) : data(vec) { const int size = data.size(); hash = std::vector<u64>(size + 1); for (const int i : rep(size)) { assert(0 <= data[i] and (u64) data[i] < Oper::MOD); hash[i + 1] = Oper::sum(Oper::product(Base::BASE, hash[i]), (u64)data[i]); } } int size() const { return data.size(); } const std::vector<T>& get() const { return data; } u64 fold() const { return hash.back(); } u64 fold(const int l, const int r) const { assert(0 <= l and l <= r and r <= size()); return Oper::difference(hash[r], Oper::product(hash[l], Base::base_pow(r - l))); } void concat(const PolynomialHash& other) { hash.reserve(hash.size() + other.size()); u64 val = hash.back(); for (const int i : rep(other.size())) { val = Oper::product(val, Base::BASE); hash.push_back(Oper::sum(val, other.hash[i + 1])); } data.reserve(data.size() + other.size()); std::copy(other.data.cbegin(), other.data.cend(), std::back_inserter(data)); } }; #line 3 "/Users/kodamankod/Desktop/CppProcon/Library/proconlib/math/rem_euclid.cpp" template <class T> constexpr T rem_euclid(T value, const T& mod) { assert(mod > 0); return (value %= mod) >= 0 ? value : value + mod; } #line 2 "/Users/kodamankod/Desktop/CppProcon/Library/proconlib/math/totient.cpp" template <class T> constexpr T totient(T x) { T ret = x; for (T i = 2; i * i <= x; ++i) { if (x % i == 0) { ret /= i; ret *= i - 1; while (x % i == 0) x /= i; } } if (x > 1) { ret /= x; ret *= x - 1; } return ret; } #line 7 "/Users/kodamankod/Desktop/CppProcon/Library/proconlib/math/static_modint.cpp" template <u32 MOD, std::enable_if_t<((u32)1 <= MOD and MOD <= ((u32)1 << 31))>* = nullptr> class StaticModint { using Self = StaticModint; static inline constexpr u32 PHI = totient(MOD); u32 v; public: static constexpr u32 mod() noexcept { return MOD; } template <class T, std::enable_if_t<std::is_integral_v<T>>* = nullptr> static constexpr T normalize(const T& x) noexcept { return rem_euclid<std::common_type_t<T, i64>>(x, MOD); } constexpr StaticModint() noexcept : v(0) {} template <class T> constexpr StaticModint(const T& x) noexcept : v(normalize(x)) {} template <class T> static constexpr Self raw(const T& x) noexcept { Self ret; ret.v = x; return ret; } constexpr u32 val() const noexcept { return v; } constexpr Self neg() const noexcept { return raw(v == 0 ? 0 : MOD - v); } constexpr Self inv() const noexcept { return pow(PHI - 1); } constexpr Self pow(u64 exp) const noexcept { Self ret(1), mult(*this); for (; exp > 0; exp >>= 1) { if (exp & 1) ret *= mult; mult *= mult; } return ret; } constexpr Self operator-() const noexcept { return neg(); } constexpr Self operator~() const noexcept { return inv(); } constexpr Self operator+(const Self& rhs) const noexcept { return Self(*this) += rhs; } constexpr Self& operator+=(const Self& rhs) noexcept { if ((v += rhs.v) >= MOD) v -= MOD; return *this; } constexpr Self operator-(const Self& rhs) const noexcept { return Self(*this) -= rhs; } constexpr Self& operator-=(const Self& rhs) noexcept { if (v < rhs.v) v += MOD; v -= rhs.v; return *this; } constexpr Self operator*(const Self& rhs) const noexcept { return Self(*this) *= rhs; } constexpr Self& operator*=(const Self& rhs) noexcept { v = (u64)v * rhs.v % MOD; return *this; } constexpr Self operator/(const Self& rhs) const noexcept { return Self(*this) /= rhs; } constexpr Self& operator/=(const Self& rhs) noexcept { return *this *= rhs.inv(); } constexpr bool operator==(const Self& rhs) const noexcept { return v == rhs.v; } constexpr bool operator!=(const Self& rhs) const noexcept { return v != rhs.v; } friend std::ostream& operator<<(std::ostream& stream, const Self& rhs) { return stream << rhs.v; } }; using Modint1000000007 = StaticModint<1000000007>; using Modint998244353 = StaticModint<998244353>; #line 7 "main.cpp" using std::vector; using std::array; using std::pair; using std::tuple; using Fp = Modint1000000007; void main_() { int N, K; std::cin >> N >> K; vector<Fp> dp(K, 1); vector<u64> hash(K); for (auto& x : hash) { char c; std::cin >> c; x = PolynomialHash(vector<char>{c}).fold(); } for (const int i : rep(2, N + 1)) { vector<Fp> next(K); vector<u64> next_hash(K); for (const int j : rep(K)) { vector<char> s(i); for (auto& x : s) { std::cin >> x; } const PolynomialHash p(s); for (const int k : rep(K)) { if (p.fold(0, i - 1) == hash[k] or p.fold(1, i) == hash[k]) { next[j] += dp[k]; } } next_hash[j] = p.fold(); } dp = std::move(next); hash = std::move(next_hash); } std::cout << std::accumulate(dp.begin(), dp.end(), Fp(0)) << '\n'; } int main() { std::ios_base::sync_with_stdio(false); std::cin.tie(nullptr); main_(); return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...