This documentation is automatically generated by online-judge-tools/verification-helper
#include "random/hash_vector.hpp"
#pragma once
#include "random/base.hpp"
#include "mod/modint61.hpp"
template <typename T>
u64 hash_vector(vc<T> X) {
using mint = modint61;
static vc<mint> hash_base;
int n = len(X);
while (len(hash_base) <= n) { hash_base.eb(RNG(mint::get_mod())); }
mint H = 0;
FOR(i, n) H += hash_base[i] * mint(X[i]);
H += hash_base[n];
return H.val;
}
template <typename T, int K>
u64 hash_array(array<T, K> X) {
using mint = modint61;
static array<mint, K> hash_base{};
if (hash_base[0] == mint(0)) FOR(i, K) hash_base[i] = RNG_64();
mint H = 0;
FOR(i, K) H += hash_base[i] * mint(X[i]);
return H.val;
}
#line 2 "random/hash_vector.hpp"
#line 2 "random/base.hpp"
u64 RNG_64() {
static u64 x_ = u64(chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count()) * 10150724397891781847ULL;
x_ ^= x_ << 7;
return x_ ^= x_ >> 9;
}
u64 RNG(u64 lim) { return RNG_64() % lim; }
ll RNG(ll l, ll r) { return l + RNG_64() % (r - l); }
#line 2 "mod/modint61.hpp"
struct modint61 {
static constexpr u64 mod = (1ULL << 61) - 1;
u64 val;
constexpr modint61() : val(0ULL) {}
constexpr modint61(u32 x) : val(x) {}
constexpr modint61(u64 x) : val(x % mod) {}
constexpr modint61(int x) : val((x < 0) ? (x + static_cast<ll>(mod)) : x) {}
constexpr modint61(ll x) : val(((x %= static_cast<ll>(mod)) < 0) ? (x + static_cast<ll>(mod)) : x) {}
static constexpr u64 get_mod() { return mod; }
modint61 &operator+=(const modint61 &a) {
val = ((val += a.val) >= mod) ? (val - mod) : val;
return *this;
}
modint61 &operator-=(const modint61 &a) {
val = ((val -= a.val) >= mod) ? (val + mod) : val;
return *this;
}
modint61 &operator*=(const modint61 &a) {
const unsigned __int128 y = static_cast<unsigned __int128>(val) * a.val;
val = (y >> 61) + (y & mod);
val = (val >= mod) ? (val - mod) : val;
return *this;
}
modint61 operator-() const { return modint61(val ? mod - val : u64(0)); }
modint61 &operator/=(const modint61 &a) { return (*this *= a.inverse()); }
modint61 operator+(const modint61 &p) const { return modint61(*this) += p; }
modint61 operator-(const modint61 &p) const { return modint61(*this) -= p; }
modint61 operator*(const modint61 &p) const { return modint61(*this) *= p; }
modint61 operator/(const modint61 &p) const { return modint61(*this) /= p; }
bool operator<(const modint61 &other) const { return val < other.val; }
bool operator==(const modint61 &p) const { return val == p.val; }
bool operator!=(const modint61 &p) const { return val != p.val; }
modint61 inverse() const {
ll a = val, b = mod, u = 1, v = 0, t;
while (b > 0) {
t = a / b;
swap(a -= t * b, b), swap(u -= t * v, v);
}
return modint61(u);
}
modint61 pow(ll n) const {
assert(n >= 0);
modint61 ret(1), mul(val);
while (n > 0) {
if (n & 1) ret *= mul;
mul *= mul, n >>= 1;
}
return ret;
}
};
#ifdef FASTIO
void rd(modint61 &x) {
fastio::rd(x.val);
assert(0 <= x.val && x.val < modint61::mod);
}
void wt(modint61 x) { fastio::wt(x.val); }
#endif
#line 5 "random/hash_vector.hpp"
template <typename T>
u64 hash_vector(vc<T> X) {
using mint = modint61;
static vc<mint> hash_base;
int n = len(X);
while (len(hash_base) <= n) { hash_base.eb(RNG(mint::get_mod())); }
mint H = 0;
FOR(i, n) H += hash_base[i] * mint(X[i]);
H += hash_base[n];
return H.val;
}
template <typename T, int K>
u64 hash_array(array<T, K> X) {
using mint = modint61;
static array<mint, K> hash_base{};
if (hash_base[0] == mint(0)) FOR(i, K) hash_base[i] = RNG_64();
mint H = 0;
FOR(i, K) H += hash_base[i] * mint(X[i]);
return H.val;
}