This documentation is automatically generated by competitive-verifier/competitive-verifier
#include "dfa/multiple_of.hpp"
#pragma once
#include "dfa.hpp"
namespace dfa {
template <class T>
struct multiple_of : dfa_default {
T d;
constexpr multiple_of(T d) : d(d) {}
using alphabet = char;
using state = T;
state init() const { return 0; }
state next(state s, alphabet a, int) const {
return (s * 10 + (a - '0')) % d;
}
bool accept(state s) const { return s == 0; }
};
} // namespace dfa
#line 2 "prelude.hpp"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vi = vector<int>;
using vvi = vector<vector<int>>;
using vll = vector<ll>;
using vvll = vector<vector<ll>>;
using vc = vector<char>;
#define rep2(i, m, n) for (auto i = (m); i < (n); i++)
#define rep(i, n) rep2(i, 0, n)
#define repr2(i, m, n) for (auto i = (n); i-- > (m);)
#define repr(i, n) repr2(i, 0, n)
#define all(x) begin(x), end(x)
auto ndvec(int n, auto e) { return vector(n, e); }
auto ndvec(int n, auto ...e) { return vector(n, ndvec(e...)); }
auto comp_key(auto&& f) { return [&](auto&& a, auto&& b) { return f(a) < f(b); }; }
auto& max(const auto& a, const auto& b) { return a < b ? b : a; }
auto& min(const auto& a, const auto& b) { return b < a ? b : a; }
#if __cpp_lib_ranges
namespace R = std::ranges;
namespace V = std::views;
#endif
#line 3 "util/seed.hpp"
auto seed() {
#if defined(LOCAL) && !defined(NO_FIX_SEED)
return 314169265258979;
#endif
return chrono::steady_clock::now().time_since_epoch().count();
}
#line 3 "util/rand.hpp"
uint32_t rand32() {
static uint32_t x = seed();
x ^= x << 13;
x ^= x >> 17;
x ^= x << 5;
return x;
}
uint64_t rand64() {
return uint64_t(rand32()) << 32 | rand32();
}
#line 3 "util/hash.hpp"
[[gnu::const]] uint64_t splitmix64(uint64_t x) {
// http://xorshift.di.unimi.it/splitmix64.c
x += 0x9e3779b97f4a7c15;
x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
return x ^ (x >> 31);
}
template <class T, class = void>
struct anti_hack_hash;
template <class T>
struct anti_hack_hash<T, enable_if_t<is_convertible_v<T, uint64_t>>> {
size_t operator()(T x) const {
static const uint64_t ofs = seed();
return splitmix64((uint64_t)x + ofs);
}
};
template <class T>
struct anti_hack_hash<T, void_t<decltype(tuple_size<T>::value)>> {
size_t operator()(const T& x) const {
return hash_impl(x, make_index_sequence<tuple_size_v<T>>{});
}
private:
static auto make_seed() {
array<uint64_t, tuple_size_v<T>> res;
res[0] = seed();
rep(i, tuple_size_v<T> - 1) res[i + 1] = splitmix64(res[i]) + seed();
return res;
}
template <size_t... Is>
static size_t hash_impl(const T& x, index_sequence<Is...>) {
size_t res = 0;
((void)(res = splitmix64(
res + anti_hack_hash<tuple_element_t<Is, T>>{}(get<Is>(x)))),
...);
return res;
}
};
#line 4 "ds/hash_map.hpp"
#include <ext/pb_ds/assoc_container.hpp>
template <class K, class V, class Hash = anti_hack_hash<K>>
using hash_map = __gnu_pbds::gp_hash_table<K, V, Hash>;
#line 4 "dfa.hpp"
namespace dfa {
struct dfa_default {
using alphabet = char;
template <class T>
bool successful(T &&) const {
return false;
}
template <class T>
bool unsuccessful(T &&) const {
return false;
}
};
struct leq_lt_base {
const char *p;
leq_lt_base(const char *p) : p(p) {}
using alphabet = char;
using state = signed char;
state init() const { return 0; }
state next(state s, alphabet a, int i) const {
return s ? s : (a > p[i]) - (a < p[i]);
}
bool successful(state s) const { return s == -1; }
bool unsuccessful(state s) const { return s == 1; }
};
struct leq : leq_lt_base {
using leq_lt_base::leq_lt_base;
bool accept(state s) const { return s != 1; }
};
struct lt : leq_lt_base {
using leq_lt_base::leq_lt_base;
bool accept(state s) const { return s == -1; }
};
template <class X>
struct lnot : X {
using X::X;
bool accept(typename lnot::state s) const { return !X::accept(s); }
bool successful(typename lnot::state s) const { return X::unsuccessful(s); }
bool unsuccessful(typename lnot::state s) const { return X::successful(s); }
};
template <class X, class... Xs>
struct land {
tuple<X, Xs...> xs;
land(X x, Xs... xs_) : xs(move(x), move(xs_)...) {}
static_assert((is_same_v<typename X::alphabet, typename Xs::alphabet> &&
... && true));
using alphabet = typename X::alphabet;
using state = tuple<typename X::state, typename Xs::state...>;
state init() const { return init(make_index_sequence<1 + sizeof...(Xs)>{}); }
template <size_t... Is>
state init(index_sequence<Is...>) const {
return tuple(get<Is>(xs).init()...);
}
state next(state s, alphabet a, int i) const {
return next(s, a, i, make_index_sequence<1 + sizeof...(Xs)>{});
}
template <size_t... Is>
state next(state s, alphabet a, int i, index_sequence<Is...>) const {
return tuple(get<Is>(xs).next(get<Is>(s), a, i)...);
}
bool accept(state s) const {
return accept(s, make_index_sequence<1 + sizeof...(Xs)>{});
}
template <size_t... Is>
bool accept(state s, index_sequence<Is...>) const {
return (get<Is>(xs).accept(get<Is>(s)) && ... && true);
}
bool successful(state s) const {
return successful(s, make_index_sequence<1 + sizeof...(Xs)>{});
}
template <size_t... Is>
bool successful(state s, index_sequence<Is...>) const {
return (get<Is>(xs).successful(get<Is>(s)) && ... && true);
}
bool unsuccessful(state s) const {
return unsuccessful(s, make_index_sequence<1 + sizeof...(Xs)>{});
}
template <size_t... Is>
bool unsuccessful(state s, index_sequence<Is...>) const {
return (get<Is>(xs).unsuccessful(get<Is>(s)) || ... || false);
}
};
const string digits = "0123456789";
template <class T, class X, class Iter = string::const_iterator>
T count(const X &dfa, int n, Iter alphabets_f = begin(digits),
Iter alphabets_l = end(digits)) {
// hash_map<typename X::state, T> prv, nxt;
map<typename X::state, T> prv, nxt;
nxt[dfa.init()] = T(1);
rep(i, n) {
prv = move(nxt);
nxt.clear();
for (auto [s, k] : prv) {
rep2(p, alphabets_f, alphabets_l) {
auto s2 = dfa.next(s, *p, i);
if (!dfa.unsuccessful(s2)) nxt[s2] += k;
}
}
}
T ans(0);
for (auto [s, k] : nxt)
if (dfa.accept(s)) ans += k;
return ans;
}
template <class T, class X, class Iter = string::const_iterator>
T sum(const X &dfa, int n, Iter alphabets_f = begin(digits),
Iter alphabets_l = end(digits)) {
hash_map<typename X::state, pair<T, T>> prv, nxt;
nxt[dfa.init()] = pair(T(0), T(1));
rep(i, n) {
prv = move(nxt);
nxt.clear();
for (auto [s, k] : prv) {
rep2(p, alphabets_f, alphabets_l) {
auto s2 = dfa.next(s, *p, i);
if (!dfa.unsuccessful(s2)) {
nxt[s2].first += k.first * 10 + (*p - '0') * k.second;
nxt[s2].second += k.second;
}
}
}
}
T ans(0);
for (auto [s, k] : nxt)
if (dfa.accept(s)) ans += k.first;
return ans;
}
} // namespace dfa
#line 3 "dfa/multiple_of.hpp"
namespace dfa {
template <class T>
struct multiple_of : dfa_default {
T d;
constexpr multiple_of(T d) : d(d) {}
using alphabet = char;
using state = T;
state init() const { return 0; }
state next(state s, alphabet a, int) const {
return (s * 10 + (a - '0')) % d;
}
bool accept(state s) const { return s == 0; }
};
} // namespace dfa