QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#843128 | #9970. Looping RPS | ucup-team133# | WA | 0ms | 3704kb | C++23 | 7.3kb | 2025-01-04 16:56:35 | 2025-01-04 16:56:36 |
Judging History
answer
#include <bits/stdc++.h>
#ifdef LOCAL
#include <debug.hpp>
#else
#define debug(...) void(0)
#endif
template <class T, class U = T> bool chmin(T& x, U&& y) {
return y < x and (x = std::forward<U>(y), true);
}
template <class T, class U = T> bool chmax(T& x, U&& y) {
return x < y and (x = std::forward<U>(y), true);
}
template <class T> void mkuni(std::vector<T>& v) {
std::ranges::sort(v);
auto result = std::ranges::unique(v);
v.erase(result.begin(), result.end());
}
template <class T> int lwb(const std::vector<T>& v, const T& x) {
return std::distance(v.begin(), std::ranges::lower_bound(v, x));
}
namespace hash_impl {
static constexpr unsigned long long mod = (1ULL << 61) - 1;
struct modint {
modint() : _v(0) {}
modint(long long v) {
unsigned long long vv = v < 0 ? v + mod : v;
vv = (vv >> 61) + (vv & mod);
if (vv >= mod) vv -= mod;
_v = vv;
}
unsigned long long val() const { return _v; }
modint& operator+=(const modint& rhs) {
_v += rhs._v;
if (_v >= mod) _v -= mod;
return *this;
}
modint& operator-=(const modint& rhs) {
if (_v < rhs._v) _v += mod;
_v -= rhs._v;
return *this;
}
modint& operator*=(const modint& rhs) {
__uint128_t t = __uint128_t(_v) * rhs._v;
t = (t >> 61) + (t & mod);
if (t >= mod) t -= mod;
_v = t;
return *this;
}
modint& operator/=(const modint& rhs) { return *this = *this * rhs.inv(); }
modint operator-() const { return modint() - *this; }
modint pow(long long n) const {
assert(0 <= n);
modint x = *this, r = 1;
while (n) {
if (n & 1) r *= x;
x *= x;
n >>= 1;
}
return r;
}
modint inv() const { return pow(mod - 2); }
friend modint operator+(const modint& lhs, const modint& rhs) { return modint(lhs) += rhs; }
friend modint operator-(const modint& lhs, const modint& rhs) { return modint(lhs) -= rhs; }
friend modint operator*(const modint& lhs, const modint& rhs) { return modint(lhs) *= rhs; }
friend modint operator/(const modint& lhs, const modint& rhs) { return modint(lhs) /= rhs; }
friend bool operator==(const modint& lhs, const modint& rhs) { return lhs._v == rhs._v; }
friend bool operator!=(const modint& lhs, const modint& rhs) { return lhs._v != rhs._v; }
friend std::ostream& operator<<(std::ostream& os, const modint& rhs) {
os << rhs._v;
return os;
}
private:
unsigned long long _v;
};
uint64_t generate_base() {
std::mt19937_64 mt(std::chrono::steady_clock::now().time_since_epoch().count());
std::uniform_int_distribution<uint64_t> rand(2, mod - 1);
return rand(mt);
}
modint base(generate_base());
std::vector<modint> power{1};
modint get_pow(int n) {
if (n < int(power.size())) return power[n];
int m = power.size();
power.resize(n + 1);
for (int i = m; i <= n; i++) power[i] = power[i - 1] * base;
return power[n];
}
}; // namespace hash_impl
struct Hash {
using mint = hash_impl::modint;
mint x;
int len;
Hash() : x(0), len(0) {}
Hash(mint x) : x(x), len(1) {}
Hash(mint x, int len) : x(x), len(len) {}
Hash& operator+=(const Hash& rhs) {
x = x * hash_impl::get_pow(rhs.len) + rhs.x;
len += rhs.len;
return *this;
}
Hash operator+(const Hash& rhs) const { return Hash(*this) += rhs; }
bool operator==(const Hash& rhs) const { return x == rhs.x and len == rhs.len; }
};
struct ReversibleHash {
using mint = hash_impl::modint;
mint x, rx;
int len;
ReversibleHash() : x(0), rx(0), len(0) {}
ReversibleHash(mint x) : x(x), rx(x), len(1) {}
ReversibleHash(mint x, mint rx, int len) : x(x), rx(rx), len(len) {}
ReversibleHash rev() const { return ReversibleHash(rx, x, len); }
ReversibleHash operator+=(const ReversibleHash& rhs) {
x = x * hash_impl::get_pow(rhs.len) + rhs.x;
rx = rx + rhs.rx * hash_impl::get_pow(len);
len += rhs.len;
return *this;
}
ReversibleHash operator+(const ReversibleHash& rhs) const { return ReversibleHash(*this) += rhs; }
bool operator==(const ReversibleHash& rhs) const { return x == rhs.x and rx == rhs.rx and len == rhs.len; }
};
using namespace std;
using ll = long long;
using mint = hash_impl::modint;
void solve() {
int n;
cin >> n;
vector<string> S(n);
for (int i = 0; i < n; i++) {
cin >> S[i];
}
vector<vector<mint>> hashes(n);
for (int i = 0; i < n; i++) {
hashes[i].emplace_back(0);
for (char& c : S[i]) {
hashes[i].emplace_back(hashes[i].back() * hash_impl::base + c);
}
}
auto f = [&](int i, int j, int len) -> mint {
assert(int(S[i].size() + S[j].size()) >= len);
int tmp = S[i].size();
if (len <= tmp) {
return hashes[i][len];
}
return hashes[i].back() * hash_impl::get_pow(len - tmp) + hashes[j][len - tmp];
};
auto lcp = [&](int i, int j) -> int {
int lb = 0, ub = int(S[i].size() + S[j].size()) + 1;
while (ub - lb > 1) {
int mid = (lb + ub) >> 1;
(f(i, j, mid) == f(j, i, mid) ? lb : ub) = mid;
}
return lb;
};
{
vector<int> ord(n);
iota(ord.begin(), ord.end(), 0);
ranges::sort(ord, [&](int i, int j) {
int l1 = S[i].size(), l2 = S[j].size();
int l = lcp(i, j);
if (l == l1 + l2) {
return false;
}
return S[i][l % l1] < S[j][l % l2];
});
vector<string> nS(n);
for (int i = 0; i < n; i++) {
nS[i] = S[ord[i]];
}
swap(S, nS);
vector<vector<mint>> nhashes(n);
for (int i = 0; i < n; i++) {
nhashes[i].emplace_back(0);
for (char& c : S[i]) {
nhashes[i].emplace_back(nhashes[i].back() * hash_impl::base + c);
}
}
swap(hashes, nhashes);
}
ll ans = 0;
auto dfs = [&](auto self, int l, int r) -> void {
if (r - l < 3) {
return;
}
int len = lcp(l, r - 1);
if (len == int(S[l].size() + S[r - 1].size())) {
return;
}
int m1, m2;
{
int lb = l, ub = r;
while (ub - lb > 1) {
int mid = (lb + ub) >> 1;
if (int(S[l].size() + S[mid].size()) < len + 1) {
lb = mid;
} else {
(f(l, mid, len + 1) == f(mid, l, len + 1) ? lb : ub) = mid;
}
}
m1 = ub;
assert(ub < r);
}
{
int lb = m1, ub = r;
while (ub - lb > 1) {
int mid = (lb + ub) >> 1;
if (int(S[l].size() + S[mid].size()) < len + 1) {
lb = mid;
} else {
(f(l, mid, len + 1) == f(mid, l, len + 1) ? lb : ub) = mid;
}
}
m2 = ub;
}
ans += 1LL * (m1 - l) * (m2 - m1) * (r - m2);
self(self, l, m1);
self(self, m1, m2);
self(self, m2, r);
};
dfs(dfs, 0, n);
cout << ans << "\n";
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout << fixed << setprecision(15);
solve();
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 0ms
memory: 3636kb
input:
6 P PN KK N PKK PN
output:
6
result:
ok 1 number(s): "6"
Test #2:
score: -100
Wrong Answer
time: 0ms
memory: 3704kb
input:
10 KKKNP KNKPPKNK KNKPP KNKPPKN KKKN NNKNNNKNNNKNNNKNNNKNNNKNNNKNNPN NNKN NPPN NNKNNNKNNNKNNNKNNNKNNNKNNNK KKKNN
output:
25
result:
wrong answer 1st numbers differ - expected: '3', found: '25'