import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.util.Arrays; import java.util.InputMismatchException; public class Main { InputStream is; PrintWriter out; String INPUT = ""; int N, M; int[] X, Y; int[] pow2 = new int[30]; void solve() { for (int i = 0; i < pow2.length; ++i) { pow2[i] = 1 << i; } long N = nl(); String[] s = new String[(int) N]; TrieByList trie = new TrieByList((int) N); for (int i = 0; i < N; ++i) { s[i] = ns(); trie.add(s[i].toCharArray(), i); } long t = System.currentTimeMillis(); trie.preLca(); SparseTable st = new SparseTable(trie.A); long M = nl(); long x = nl(); long d = nl(); long ans = 0; long nn = N * (N - 1); for (int k = 0; k < M; ++k) { int i = (int) (x / (N - 1)) + 1; int j = (int) (x % (N - 1)) + 1; if (i > j) { int tmp = i; i = j; j = tmp; } else { j = j + 1; } x = (x + d) % nn; --i; --j; if (trie.pos[trie.rev[i]] > trie.pos[trie.rev[j]]) { int tmp = i; i = j; j = tmp; } ans += st.query(trie.pos[trie.rev[i]], trie.pos[trie.rev[j]] + 1); } out.println(ans); } class SparseTable { int[][] t; public SparseTable(int[] A) { int N = A.length; t = new int[f(N) + 1][N]; // t[0] = new int[(int) N]; for (int i = 0; i < N; ++i) { t[0][i] = A[i]; } for (int i = 1; i < t.length; ++i) { int p = N - pow2[i]; // t[i] = new int[p]; for (int j = 0; j < p; ++j) { t[i][j] = Math.min(t[i - 1][j], t[i - 1][j + pow2[i - 1]]); } } } int query(int l, int r) { int a = f(r - l); return Math.min(t[a][l], t[a][r - pow2[a]]); } } // 1< 1) { int m = (h + l) / 2; if (pow2[m] <= ciel) { l = m; } else { h = m; } } return l; } class TrieByList { Node root = new Node(0, (char) -1); int gen = 1; int[] A; int[] pos; int[] rev; public TrieByList(int N) { rev = new int[N]; Arrays.fill(rev, -1); } class Node { int id; char c; Node[] child = null; int ptn = 0; int p = 0; int hit = 0; int depth = -Integer.MAX_VALUE / 16; public Node(int id, char c) { this.id = id; this.c = c; } Node search(char c) { if (ptn << 31 - (c - 'a') < 0) { return child[Integer.bitCount(ptn << 31 - (c - 'a')) - 1]; } else { return null; } } void append(Node n) { if (p == 0) { child = new Node[1]; } else if (p + 1 > child.length) { child = Arrays.copyOf(child, child.length * 2); } int zind = Integer.bitCount(ptn << 31 - (n.c - 'a')); System.arraycopy(child, zind, child, zind + 1, p - zind); child[zind] = n; ptn |= 1 << (n.c - 'a'); ++p; } } void add(char[] s, int id) { Node pre = null; Node cur = root; for (char c : s) { pre = cur; cur = pre.search(c); if (cur == null) { cur = new Node(gen++, c); pre.append(cur); } } ++cur.hit; rev[id] = cur.id; } void preLca() { A = new int[4 * gen]; pos = new int[gen]; Arrays.fill(pos, -1); root.depth = 0; dfs(root); } int tmp = 0; void dfs(Node cur) { if (pos[cur.id] == -1) { pos[cur.id] = tmp; } A[tmp++] = cur.depth; for (int i = 0; i < cur.p; ++i) { A[tmp++] = cur.depth; cur.child[i].depth = cur.depth + 1; dfs(cur.child[i]); A[tmp++] = cur.depth; } A[tmp++] = cur.depth; } } void run() throws Exception { is = INPUT.isEmpty() ? System.in : new ByteArrayInputStream(INPUT.getBytes()); out = new PrintWriter(System.out); long s = System.currentTimeMillis(); solve(); out.flush(); if (!INPUT.isEmpty()) tr(System.currentTimeMillis() - s + "ms"); // Thread t = new Thread(null, null, "~", // Runtime.getRuntime().maxMemory()){ // @Override // public void run() { // long s = System.currentTimeMillis(); // solve(); // out.flush(); // if(!INPUT.isEmpty())tr(System.currentTimeMillis()-s+"ms"); // } // }; // t.start(); // t.join(); } public static void main(String[] args) throws Exception { new Main().run(); } private byte[] inbuf = new byte[1024]; public int lenbuf = 0, ptrbuf = 0; private int readByte() { if (lenbuf == -1) throw new InputMismatchException(); if (ptrbuf >= lenbuf) { ptrbuf = 0; try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); } if (lenbuf <= 0) return -1; } return inbuf[ptrbuf++]; } private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); } private int skip() { int b; while ((b = readByte()) != -1 && isSpaceChar(b)) ; return b; } private double nd() { return Double.parseDouble(ns()); } private char nc() { return (char) skip(); } private String ns() { int b = skip(); StringBuilder sb = new StringBuilder(); while (!(isSpaceChar(b))) { // when nextLine, (isSpaceChar(b) && b != ' // ') sb.appendCodePoint(b); b = readByte(); } return sb.toString(); } private char[] ns(int n) { char[] buf = new char[n]; int b = skip(), p = 0; while (p < n && !(isSpaceChar(b))) { buf[p++] = (char) b; b = readByte(); } return n == p ? buf : Arrays.copyOf(buf, p); } private int[] na(int n) { int[] a = new int[n]; for (int i = 0; i < n; i++) a[i] = ni(); return a; } private long[] nal(int n) { long[] a = new long[n]; for (int i = 0; i < n; i++) a[i] = nl(); return a; } private char[][] nm(int n, int m) { char[][] map = new char[n][]; for (int i = 0; i < n; i++) map[i] = ns(m); return map; } private int[][] nmi(int n, int m) { int[][] map = new int[n][]; for (int i = 0; i < n; i++) map[i] = na(m); return map; } private int ni() { return (int) nl(); } private long nl() { long num = 0; int b; boolean minus = false; while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ; if (b == '-') { minus = true; b = readByte(); } while (true) { if (b >= '0' && b <= '9') { num = num * 10 + (b - '0'); } else { return minus ? -num : num; } b = readByte(); } } private static void tr(Object... o) { System.out.println(Arrays.deepToString(o)); } }