#include #ifdef DEBUG #include "libs/debug.cpp" #define DEBUG 1 #else #define DEBUG 0 #endif #define rep(i, n) repr((i), 0, (n)) #define repr(i, a, t) reps((i), (a), (t), 1) #define reps(i, a, t, s) for (long long (i) = (a); (i) < (long long)(t); (i) += (s)) #define rrep(i, n) rrepr((i), (n) - 1, 0) #define rrepr(i, a, t) rreps((i), (a), (t), 1) #define rreps(i, a, t, s) for (long long (i) = (a); (i) >= (long long)(t); (i) -= (s)) #define each(v, c) for (auto &&(v) : (c)) #define all(c) (c).begin(), (c).end() using namespace std; using ll = long long; using ull = unsigned long long; using ld = long double; template const long long MOD = 1e9 + 7; const long long INF = 1e18; /** * 構築 O(NlogN)、クエリ O(1) * @tparam T */ template class SparseTable { private: vector values; vector> table; vector msb; function fn; static vector> build(const vector &values, function fn) { unsigned long size = (unsigned long) log2(values.size()) + 1; vector> st(values.size(), vector(size)); for (unsigned long i = 0; i < values.size(); ++i) st[i][0] = i; for (unsigned long p = 1; p < size; ++p) { for (unsigned long i = 0; i < values.size(); ++i) { unsigned long q = min(i + (1 << (p - 1)), (unsigned long) values.size() - 1); unsigned long l = st[i][p - 1]; unsigned long r = st[q][p - 1]; if (values[l] == fn(values[l], values[r])) { st[i][p] = l; } else { st[i][p] = r; } } } return st; } public: SparseTable(const vector &values, function fn) { this->values = values; this->fn = fn; // table[i][p]: [i, i + 2^p) に fn を適用した結果の値のインデックス table = build(values, fn); // msb[i]: 最上位ビット; どの p を見るべきか msb = vector(values.size() + 1); for (unsigned long i = 2; i < values.size() + 1; ++i) { msb[i] = msb[i >> 1] + 1; } } /** * [a, b) に fn を適用した結果 */ T get(unsigned long a, unsigned long b) { if (b <= a) throw invalid_argument("a < b でないといけません"); if (b > values.size()) throw invalid_argument("範囲外です"); unsigned long p = msb[b - a]; return fn(values[table[a][p]], values[table[b - (1 << p)][p]]); } }; template vector argsort(const vector &vec) { vector> values; vector ret; for (unsigned long i = 0; i < vec.size(); ++i) values.emplace_back(vec[i], i); sort(values.begin(), values.end()); for (const auto &item: values) ret.push_back(item.second); return ret; } vector> genq(ll N, ll M, ll X, ll D) { vector> ret; repr (k, 1, M + 1) { ll i, j; i = (X / (N - 1)) + 1; j = (X % (N - 1)) + 1; if (i > j) swap(i, j); else j++; ret.emplace_back(i, j); X = (X + D) % (N * (N - 1)); } return ret; } int main() { cout << fixed << setprecision(10); cin.tie(nullptr); ios::sync_with_stdio(false); ifstream ifs; if (DEBUG) { ifs.open("src/_in.txt"); cin.rdbuf(ifs.rdbuf()); } ll N; cin >> N; vector S; rep (i, N) { string v0; cin >> v0; S.push_back(v0); } ll M, X, D; cin >> M >> X >> D; auto idx = argsort(argsort(S)); sort(all(S)); // lcp[i]: S[i] と S[i + 1] の共通接頭辞の長さ vector lcp(N - 1); rep (i, N - 1) { ll j = 0; while (j < S[i].size() && j < S[i + 1].size() && S[i][j] == S[i + 1][j]) ++j; lcp[i] = j; } auto st = SparseTable(lcp, [](ll a, ll b) { return min(a, b); }); ll ans = 0; auto queries = genq(N, M, X, D); each (query, queries) { ll i, j; tie(i, j) = query; i = idx[i - 1]; j = idx[j - 1]; if (i > j) swap(i, j); ans += st.get(i, j); } cout << ans << "\n"; }