import java.util.*; public class Main { public static final int MOD998 = 998244353; public static final int MOD100 = 1000000007; public static void main(String[] args) throws Exception { ContestScanner sc = new ContestScanner(); ContestPrinter cp = new ContestPrinter(); int T = sc.nextInt(); for (int t = 0; t < T; t++) { long N = sc.nextInt(); cp.println(N * (N + 1)); } cp.close(); } static class ContestScanner { private final java.io.InputStream in; private final byte[] buffer = new byte[1024]; private int ptr = 0; private int buflen = 0; private static final long LONG_MAX_TENTHS = 922337203685477580L; private static final int LONG_MAX_LAST_DIGIT = 7; private static final int LONG_MIN_LAST_DIGIT = 8; public ContestScanner(java.io.InputStream in) { this.in = in; } public ContestScanner() { this(System.in); } private boolean hasNextByte() { if (ptr < buflen) { return true; } else { ptr = 0; try { buflen = in.read(buffer); } catch (java.io.IOException e) { e.printStackTrace(); } if (buflen <= 0) { return false; } } return true; } private int readByte() { if (hasNextByte()) return buffer[ptr++]; else return -1; } private static boolean isPrintableChar(int c) { return 33 <= c && c <= 126; } public boolean hasNext() { while (hasNextByte() && !isPrintableChar(buffer[ptr])) ptr++; return hasNextByte(); } public String next() { if (!hasNext()) throw new java.util.NoSuchElementException(); StringBuilder sb = new StringBuilder(); int b = readByte(); while (isPrintableChar(b)) { sb.appendCodePoint(b); b = readByte(); } return sb.toString(); } public long nextLong() { if (!hasNext()) throw new java.util.NoSuchElementException(); long n = 0; boolean minus = false; int b = readByte(); if (b == '-') { minus = true; b = readByte(); } if (b < '0' || '9' < b) { throw new NumberFormatException(); } while (true) { if ('0' <= b && b <= '9') { int digit = b - '0'; if (n >= LONG_MAX_TENTHS) { if (n == LONG_MAX_TENTHS) { if (minus) { if (digit <= LONG_MIN_LAST_DIGIT) { n = -n * 10 - digit; b = readByte(); if (!isPrintableChar(b)) { return n; } else if (b < '0' || '9' < b) { throw new NumberFormatException( String.format("%d%s... is not number", n, Character.toString(b))); } } } else { if (digit <= LONG_MAX_LAST_DIGIT) { n = n * 10 + digit; b = readByte(); if (!isPrintableChar(b)) { return n; } else if (b < '0' || '9' < b) { throw new NumberFormatException( String.format("%d%s... is not number", n, Character.toString(b))); } } } } throw new ArithmeticException( String.format("%s%d%d... overflows long.", minus ? "-" : "", n, digit)); } n = n * 10 + digit; } else if (b == -1 || !isPrintableChar(b)) { return minus ? -n : n; } else { throw new NumberFormatException(); } b = readByte(); } } public int nextInt() { long nl = nextLong(); if (nl < Integer.MIN_VALUE || nl > Integer.MAX_VALUE) throw new NumberFormatException(); return (int) nl; } public double nextDouble() { return Double.parseDouble(next()); } public long[] nextLongArray(int length) { long[] array = new long[length]; for (int i = 0; i < length; i++) array[i] = this.nextLong(); return array; } public long[] nextLongArray(int length, java.util.function.LongUnaryOperator map) { long[] array = new long[length]; for (int i = 0; i < length; i++) array[i] = map.applyAsLong(this.nextLong()); return array; } public int[] nextIntArray(int length) { int[] array = new int[length]; for (int i = 0; i < length; i++) array[i] = this.nextInt(); return array; } public int[][] nextIntArrayMulti(int length, int width) { int[][] arrays = new int[width][length]; for (int i = 0; i < length; i++) { for (int j = 0; j < width; j++) arrays[j][i] = this.nextInt(); } return arrays; } public int[] nextIntArray(int length, java.util.function.IntUnaryOperator map) { int[] array = new int[length]; for (int i = 0; i < length; i++) array[i] = map.applyAsInt(this.nextInt()); return array; } public double[] nextDoubleArray(int length) { double[] array = new double[length]; for (int i = 0; i < length; i++) array[i] = this.nextDouble(); return array; } public double[] nextDoubleArray(int length, java.util.function.DoubleUnaryOperator map) { double[] array = new double[length]; for (int i = 0; i < length; i++) array[i] = map.applyAsDouble(this.nextDouble()); return array; } public long[][] nextLongMatrix(int height, int width) { long[][] mat = new long[height][width]; for (int h = 0; h < height; h++) for (int w = 0; w < width; w++) { mat[h][w] = this.nextLong(); } return mat; } public int[][] nextIntMatrix(int height, int width) { int[][] mat = new int[height][width]; for (int h = 0; h < height; h++) for (int w = 0; w < width; w++) { mat[h][w] = this.nextInt(); } return mat; } public double[][] nextDoubleMatrix(int height, int width) { double[][] mat = new double[height][width]; for (int h = 0; h < height; h++) for (int w = 0; w < width; w++) { mat[h][w] = this.nextDouble(); } return mat; } public char[][] nextCharMatrix(int height, int width) { char[][] mat = new char[height][width]; for (int h = 0; h < height; h++) { String s = this.next(); for (int w = 0; w < width; w++) { mat[h][w] = s.charAt(w); } } return mat; } } static class ContestPrinter extends java.io.PrintWriter { public ContestPrinter(java.io.PrintStream stream) { super(stream); } public ContestPrinter() { super(System.out); } private static String dtos(double x, int n) { StringBuilder sb = new StringBuilder(); if (x < 0) { sb.append('-'); x = -x; } x += Math.pow(10, -n) / 2; sb.append((long) x); sb.append("."); x -= (long) x; for (int i = 0; i < n; i++) { x *= 10; sb.append((int) x); x -= (int) x; } return sb.toString(); } @Override public void print(float f) { super.print(dtos(f, 20)); } @Override public void println(float f) { super.println(dtos(f, 20)); } @Override public void print(double d) { super.print(dtos(d, 20)); } @Override public void println(double d) { super.println(dtos(d, 20)); } public void printArray(int[] array, String separator) { int n = array.length; for (int i = 0; i < n - 1; i++) { super.print(array[i]); super.print(separator); } super.println(array[n - 1]); } public void printArray(int[] array) { this.printArray(array, " "); } public void printArray(int[] array, String separator, java.util.function.IntUnaryOperator map) { int n = array.length; for (int i = 0; i < n - 1; i++) { super.print(map.applyAsInt(array[i])); super.print(separator); } super.println(map.applyAsInt(array[n - 1])); } public void printArray(int[] array, java.util.function.IntUnaryOperator map) { this.printArray(array, " ", map); } public void printArray(long[] array, String separator) { int n = array.length; for (int i = 0; i < n - 1; i++) { super.print(array[i]); super.print(separator); } super.println(array[n - 1]); } public void printArray(long[] array) { this.printArray(array, " "); } public void printArray(long[] array, String separator, java.util.function.LongUnaryOperator map) { int n = array.length; for (int i = 0; i < n - 1; i++) { super.print(map.applyAsLong(array[i])); super.print(separator); } super.println(map.applyAsLong(array[n - 1])); } public void printArray(long[] array, java.util.function.LongUnaryOperator map) { this.printArray(array, " ", map); } } static class Permutation implements java.util.Iterator, Iterable { private int[] next; public Permutation(int n) { next = java.util.stream.IntStream.range(0, n).toArray(); } @Override public boolean hasNext() { return next != null; } @Override public int[] next() { int[] r = next.clone(); next = nextPermutation(next); return r; } @Override public java.util.Iterator iterator() { return this; } public static int[] nextPermutation(int[] a) { if (a == null || a.length < 2) return null; int p = 0; for (int i = a.length - 2; i >= 0; i--) { if (a[i] >= a[i + 1]) continue; p = i; break; } int q = 0; for (int i = a.length - 1; i > p; i--) { if (a[i] <= a[p]) continue; q = i; break; } if (p == 0 && q == 0) return null; int temp = a[p]; a[p] = a[q]; a[q] = temp; int l = p, r = a.length; while (++l < --r) { temp = a[l]; a[l] = a[r]; a[r] = temp; } return a; } } static class SegTree { final int MAX; final int N; final java.util.function.BinaryOperator op; final S E; final S[] data; @SuppressWarnings("unchecked") public SegTree(int n, java.util.function.BinaryOperator op, S e) { this.MAX = n; int k = 1; while (k < n) k <<= 1; this.N = k; this.E = e; this.op = op; this.data = (S[]) new Object[N << 1]; java.util.Arrays.fill(data, E); } public SegTree(S[] dat, java.util.function.BinaryOperator op, S e) { this(dat.length, op, e); build(dat); } private void build(S[] dat) { int l = dat.length; System.arraycopy(dat, 0, data, N, l); for (int i = N - 1; i > 0; i--) { data[i] = op.apply(data[i << 1 | 0], data[i << 1 | 1]); } } public void set(int p, S x) { exclusiveRangeCheck(p); data[p += N] = x; p >>= 1; while (p > 0) { data[p] = op.apply(data[p << 1 | 0], data[p << 1 | 1]); p >>= 1; } } public S get(int p) { exclusiveRangeCheck(p); return data[p + N]; } public S prod(int l, int r) { if (l > r) { throw new IllegalArgumentException(String.format("Invalid range: [%d, %d)", l, r)); } inclusiveRangeCheck(l); inclusiveRangeCheck(r); S sumLeft = E; S sumRight = E; l += N; r += N; while (l < r) { if ((l & 1) == 1) sumLeft = op.apply(sumLeft, data[l++]); if ((r & 1) == 1) sumRight = op.apply(data[--r], sumRight); l >>= 1; r >>= 1; } return op.apply(sumLeft, sumRight); } public S allProd() { return data[1]; } public int maxRight(int l, java.util.function.Predicate f) { inclusiveRangeCheck(l); if (!f.test(E)) { throw new IllegalArgumentException("Identity element must satisfy the condition."); } if (l == MAX) return MAX; l += N; S sum = E; do { l >>= Integer.numberOfTrailingZeros(l); if (!f.test(op.apply(sum, data[l]))) { while (l < N) { l = l << 1; if (f.test(op.apply(sum, data[l]))) { sum = op.apply(sum, data[l]); l++; } } return l - N; } sum = op.apply(sum, data[l]); l++; } while ((l & -l) != l); return MAX; } public int minLeft(int r, java.util.function.Predicate f) { inclusiveRangeCheck(r); if (!f.test(E)) { throw new IllegalArgumentException("Identity element must satisfy the condition."); } if (r == 0) return 0; r += N; S sum = E; do { r--; while (r > 1 && (r & 1) == 1) r >>= 1; if (!f.test(op.apply(data[r], sum))) { while (r < N) { r = r << 1 | 1; if (f.test(op.apply(data[r], sum))) { sum = op.apply(data[r], sum); r--; } } return r + 1 - N; } sum = op.apply(data[r], sum); } while ((r & -r) != r); return 0; } private void exclusiveRangeCheck(int p) { if (p < 0 || p >= MAX) { throw new IndexOutOfBoundsException( String.format("Index %d out of bounds for the range [%d, %d).", p, 0, MAX)); } } private void inclusiveRangeCheck(int p) { if (p < 0 || p > MAX) { throw new IndexOutOfBoundsException( String.format("Index %d out of bounds for the range [%d, %d].", p, 0, MAX)); } } // **************** DEBUG **************** // private int indent = 6; public void setIndent(int newIndent) { this.indent = newIndent; } @Override public String toString() { return toSimpleString(); } public String toDetailedString() { return toDetailedString(1, 0); } private String toDetailedString(int k, int sp) { if (k >= N) return indent(sp) + data[k]; String s = ""; s += toDetailedString(k << 1 | 1, sp + indent); s += "\n"; s += indent(sp) + data[k]; s += "\n"; s += toDetailedString(k << 1 | 0, sp + indent); return s; } private static String indent(int n) { StringBuilder sb = new StringBuilder(); while (n-- > 0) sb.append(' '); return sb.toString(); } public String toSimpleString() { StringBuilder sb = new StringBuilder(); sb.append('['); for (int i = 0; i < N; i++) { sb.append(data[i + N]); if (i < N - 1) sb.append(',').append(' '); } sb.append(']'); return sb.toString(); } } static class LazySegTree { final int MAX; final int N; final int Log; final java.util.function.BinaryOperator Op; final S E; final java.util.function.BiFunction Mapping; final java.util.function.BinaryOperator Composition; final Func Id; final S[] Dat; final Func[] Laz; @SuppressWarnings("unchecked") public LazySegTree(int n, java.util.function.BinaryOperator op, S e, java.util.function.BiFunction mapping, java.util.function.BinaryOperator composition, Func id) { this.MAX = n; int k = 1; while (k < n) k <<= 1; this.N = k; this.Log = Integer.numberOfTrailingZeros(N); this.Op = op; this.E = e; this.Mapping = mapping; this.Composition = composition; this.Id = id; this.Dat = (S[]) new Object[N << 1]; this.Laz = (Func[]) new Object[N]; java.util.Arrays.fill(Dat, E); java.util.Arrays.fill(Laz, Id); } public LazySegTree(S[] dat, java.util.function.BinaryOperator op, S e, java.util.function.BiFunction mapping, java.util.function.BinaryOperator composition, Func id) { this(dat.length, op, e, mapping, composition, id); build(dat); } private void build(S[] dat) { int l = dat.length; System.arraycopy(dat, 0, Dat, N, l); for (int i = N - 1; i > 0; i--) { Dat[i] = Op.apply(Dat[i << 1 | 0], Dat[i << 1 | 1]); } } private void push(int k) { if (Laz[k] == Id) return; int lk = k << 1 | 0, rk = k << 1 | 1; Dat[lk] = Mapping.apply(Laz[k], Dat[lk]); Dat[rk] = Mapping.apply(Laz[k], Dat[rk]); if (lk < N) Laz[lk] = Composition.apply(Laz[k], Laz[lk]); if (rk < N) Laz[rk] = Composition.apply(Laz[k], Laz[rk]); Laz[k] = Id; } private void pushTo(int k) { for (int i = Log; i > 0; i--) push(k >> i); } private void pushTo(int lk, int rk) { for (int i = Log; i > 0; i--) { if (((lk >> i) << i) != lk) push(lk >> i); if (((rk >> i) << i) != rk) push(rk >> i); } } private void updateFrom(int k) { k >>= 1; while (k > 0) { Dat[k] = Op.apply(Dat[k << 1 | 0], Dat[k << 1 | 1]); k >>= 1; } } private void updateFrom(int lk, int rk) { for (int i = 1; i <= Log; i++) { if (((lk >> i) << i) != lk) { int lki = lk >> i; Dat[lki] = Op.apply(Dat[lki << 1 | 0], Dat[lki << 1 | 1]); } if (((rk >> i) << i) != rk) { int rki = (rk - 1) >> i; Dat[rki] = Op.apply(Dat[rki << 1 | 0], Dat[rki << 1 | 1]); } } } public void set(int p, S x) { exclusiveRangeCheck(p); p += N; pushTo(p); Dat[p] = x; updateFrom(p); } public S get(int p) { exclusiveRangeCheck(p); p += N; pushTo(p); return Dat[p]; } public S prod(int l, int r) { if (l > r) { throw new IllegalArgumentException(String.format("Invalid range: [%d, %d)", l, r)); } inclusiveRangeCheck(l); inclusiveRangeCheck(r); if (l == r) return E; l += N; r += N; pushTo(l, r); S sumLeft = E, sumRight = E; while (l < r) { if ((l & 1) == 1) sumLeft = Op.apply(sumLeft, Dat[l++]); if ((r & 1) == 1) sumRight = Op.apply(Dat[--r], sumRight); l >>= 1; r >>= 1; } return Op.apply(sumLeft, sumRight); } public S allProd() { return Dat[1]; } public void apply(int p, Func f) { exclusiveRangeCheck(p); p += N; pushTo(p); Dat[p] = Mapping.apply(f, Dat[p]); updateFrom(p); } public void apply(int l, int r, Func f) { if (l > r) { throw new IllegalArgumentException(String.format("Invalid range: [%d, %d)", l, r)); } inclusiveRangeCheck(l); inclusiveRangeCheck(r); if (l == r) return; l += N; r += N; pushTo(l, r); for (int l2 = l, r2 = r; l2 < r2;) { if ((l2 & 1) == 1) { Dat[l2] = Mapping.apply(f, Dat[l2]); if (l2 < N) Laz[l2] = Composition.apply(f, Laz[l2]); l2++; } if ((r2 & 1) == 1) { r2--; Dat[r2] = Mapping.apply(f, Dat[r2]); if (r2 < N) Laz[r2] = Composition.apply(f, Laz[r2]); } l2 >>= 1; r2 >>= 1; } updateFrom(l, r); } public int maxRight(int l, java.util.function.Predicate g) { inclusiveRangeCheck(l); if (!g.test(E)) { throw new IllegalArgumentException("Identity element must satisfy the condition."); } if (l == MAX) return MAX; l += N; pushTo(l); S sum = E; do { l >>= Integer.numberOfTrailingZeros(l); if (!g.test(Op.apply(sum, Dat[l]))) { while (l < N) { push(l); l = l << 1; if (g.test(Op.apply(sum, Dat[l]))) { sum = Op.apply(sum, Dat[l]); l++; } } return l - N; } sum = Op.apply(sum, Dat[l]); l++; } while ((l & -l) != l); return MAX; } public int minLeft(int r, java.util.function.Predicate g) { inclusiveRangeCheck(r); if (!g.test(E)) { throw new IllegalArgumentException("Identity element must satisfy the condition."); } if (r == 0) return 0; r += N; pushTo(r - 1); S sum = E; do { r--; while (r > 1 && (r & 1) == 1) r >>= 1; if (!g.test(Op.apply(Dat[r], sum))) { while (r < N) { push(r); r = r << 1 | 1; if (g.test(Op.apply(Dat[r], sum))) { sum = Op.apply(Dat[r], sum); r--; } } return r + 1 - N; } sum = Op.apply(Dat[r], sum); } while ((r & -r) != r); return 0; } private void exclusiveRangeCheck(int p) { if (p < 0 || p >= MAX) { throw new IndexOutOfBoundsException(String.format("Index %d is not in [%d, %d).", p, 0, MAX)); } } private void inclusiveRangeCheck(int p) { if (p < 0 || p > MAX) { throw new IndexOutOfBoundsException(String.format("Index %d is not in [%d, %d].", p, 0, MAX)); } } // **************** DEBUG **************** // private int indent = 6; public void setIndent(int newIndent) { this.indent = newIndent; } @Override public String toString() { return toSimpleString(); } private S[] simulatePushAll() { S[] simDat = java.util.Arrays.copyOf(Dat, 2 * N); Func[] simLaz = java.util.Arrays.copyOf(Laz, 2 * N); for (int k = 1; k < N; k++) { if (simLaz[k] == Id) continue; int lk = k << 1 | 0, rk = k << 1 | 1; simDat[lk] = Mapping.apply(simLaz[k], simDat[lk]); simDat[rk] = Mapping.apply(simLaz[k], simDat[rk]); if (lk < N) simLaz[lk] = Composition.apply(simLaz[k], simLaz[lk]); if (rk < N) simLaz[rk] = Composition.apply(simLaz[k], simLaz[rk]); simLaz[k] = Id; } return simDat; } public String toDetailedString() { return toDetailedString(1, 0, simulatePushAll()); } private String toDetailedString(int k, int sp, S[] dat) { if (k >= N) return indent(sp) + dat[k]; String s = ""; s += toDetailedString(k << 1 | 1, sp + indent, dat); s += "\n"; s += indent(sp) + dat[k]; s += "\n"; s += toDetailedString(k << 1 | 0, sp + indent, dat); return s; } private static String indent(int n) { StringBuilder sb = new StringBuilder(); while (n-- > 0) sb.append(' '); return sb.toString(); } public String toSimpleString() { S[] dat = simulatePushAll(); StringBuilder sb = new StringBuilder(); sb.append('['); for (int i = 0; i < N; i++) { sb.append(dat[i + N]); if (i < N - 1) sb.append(',').append(' '); } sb.append(']'); return sb.toString(); } } static class MaxFlow { private static final class InternalCapEdge { final int to; final int rev; long cap; InternalCapEdge(int to, int rev, long cap) { this.to = to; this.rev = rev; this.cap = cap; } } public static final class CapEdge { public final int from, to; public final long cap, flow; CapEdge(int from, int to, long cap, long flow) { this.from = from; this.to = to; this.cap = cap; this.flow = flow; } @Override public boolean equals(Object o) { if (o instanceof CapEdge) { CapEdge e = (CapEdge) o; return from == e.from && to == e.to && cap == e.cap && flow == e.flow; } return false; } } private static final class IntPair { final int first, second; IntPair(int first, int second) { this.first = first; this.second = second; } } static final long INF = Long.MAX_VALUE; private final int n; private final java.util.ArrayList pos; private final java.util.ArrayList[] g; @SuppressWarnings("unchecked") public MaxFlow(int n) { this.n = n; this.pos = new java.util.ArrayList<>(); this.g = new java.util.ArrayList[n]; for (int i = 0; i < n; i++) { this.g[i] = new java.util.ArrayList<>(); } } public int addEdge(int from, int to, long cap) { rangeCheck(from, 0, n); rangeCheck(to, 0, n); nonNegativeCheck(cap, "Capacity"); int m = pos.size(); pos.add(new IntPair(from, g[from].size())); int fromId = g[from].size(); int toId = g[to].size(); if (from == to) toId++; g[from].add(new InternalCapEdge(to, toId, cap)); g[to].add(new InternalCapEdge(from, fromId, 0L)); return m; } private InternalCapEdge getInternalEdge(int i) { return g[pos.get(i).first].get(pos.get(i).second); } private InternalCapEdge getInternalEdgeReversed(InternalCapEdge e) { return g[e.to].get(e.rev); } public CapEdge getEdge(int i) { int m = pos.size(); rangeCheck(i, 0, m); InternalCapEdge e = getInternalEdge(i); InternalCapEdge re = getInternalEdgeReversed(e); return new CapEdge(re.to, e.to, e.cap + re.cap, re.cap); } public CapEdge[] getEdges() { CapEdge[] res = new CapEdge[pos.size()]; java.util.Arrays.setAll(res, this::getEdge); return res; } public void changeEdge(int i, long newCap, long newFlow) { int m = pos.size(); rangeCheck(i, 0, m); nonNegativeCheck(newCap, "Capacity"); if (newFlow > newCap) { throw new IllegalArgumentException( String.format("Flow %d is greater than the capacity %d.", newCap, newFlow)); } InternalCapEdge e = getInternalEdge(i); InternalCapEdge re = getInternalEdgeReversed(e); e.cap = newCap - newFlow; re.cap = newFlow; } public long maxFlow(int s, int t) { return flow(s, t, INF); } public long flow(int s, int t, long flowLimit) { rangeCheck(s, 0, n); rangeCheck(t, 0, n); long flow = 0L; int[] level = new int[n]; int[] que = new int[n]; int[] iter = new int[n]; while (flow < flowLimit) { bfs(s, t, level, que); if (level[t] < 0) break; java.util.Arrays.fill(iter, 0); while (flow < flowLimit) { long d = dfs(t, s, flowLimit - flow, iter, level); if (d == 0) break; flow += d; } } return flow; } private void bfs(int s, int t, int[] level, int[] que) { java.util.Arrays.fill(level, -1); int hd = 0, tl = 0; que[tl++] = s; level[s] = 0; while (hd < tl) { int u = que[hd++]; for (InternalCapEdge e : g[u]) { int v = e.to; if (e.cap == 0 || level[v] >= 0) continue; level[v] = level[u] + 1; if (v == t) return; que[tl++] = v; } } } private long dfs(int cur, int s, long flowLimit, int[] iter, int[] level) { if (cur == s) return flowLimit; long res = 0; int curLevel = level[cur]; for (int itMax = g[cur].size(); iter[cur] < itMax; iter[cur]++) { int i = iter[cur]; InternalCapEdge e = g[cur].get(i); InternalCapEdge re = getInternalEdgeReversed(e); if (curLevel <= level[e.to] || re.cap == 0) continue; long d = dfs(e.to, s, Math.min(flowLimit - res, re.cap), iter, level); if (d <= 0) continue; e.cap += d; re.cap -= d; res += d; if (res == flowLimit) break; } return res; } public boolean[] minCut(int s) { rangeCheck(s, 0, n); boolean[] visited = new boolean[n]; int[] stack = new int[n]; int ptr = 0; stack[ptr++] = s; visited[s] = true; while (ptr > 0) { int u = stack[--ptr]; for (InternalCapEdge e : g[u]) { int v = e.to; if (e.cap > 0 && !visited[v]) { visited[v] = true; stack[ptr++] = v; } } } return visited; } private void rangeCheck(int i, int minInclusive, int maxExclusive) { if (i < 0 || i >= maxExclusive) { throw new IndexOutOfBoundsException( String.format("Index %d out of bounds for length %d", i, maxExclusive)); } } private void nonNegativeCheck(long cap, String attribute) { if (cap < 0) { throw new IllegalArgumentException(String.format("%s %d is negative.", attribute, cap)); } } } static class StringAlgorithm { private static int[] saNaive(int[] s) { int n = s.length; int[] sa = new int[n]; for (int i = 0; i < n; i++) { sa[i] = i; } insertionsortUsingComparator(sa, (l, r) -> { while (l < n && r < n) { if (s[l] != s[r]) return s[l] - s[r]; l++; r++; } return -(l - r); }); return sa; } public static int[] saDoubling(int[] s) { int n = s.length; int[] sa = new int[n]; for (int i = 0; i < n; i++) { sa[i] = i; } int[] rnk = java.util.Arrays.copyOf(s, n); int[] tmp = new int[n]; for (int k = 1; k < n; k *= 2) { final int _k = k; final int[] _rnk = rnk; java.util.function.IntBinaryOperator cmp = (x, y) -> { if (_rnk[x] != _rnk[y]) return _rnk[x] - _rnk[y]; int rx = x + _k < n ? _rnk[x + _k] : -1; int ry = y + _k < n ? _rnk[y + _k] : -1; return rx - ry; }; mergesortUsingComparator(sa, cmp); tmp[sa[0]] = 0; for (int i = 1; i < n; i++) { tmp[sa[i]] = tmp[sa[i - 1]] + (cmp.applyAsInt(sa[i - 1], sa[i]) < 0 ? 1 : 0); } int[] buf = tmp; tmp = rnk; rnk = buf; } return sa; } private static void insertionsortUsingComparator(int[] a, java.util.function.IntBinaryOperator comparator) { final int n = a.length; for (int i = 1; i < n; i++) { final int tmp = a[i]; if (comparator.applyAsInt(a[i - 1], tmp) > 0) { int j = i; do { a[j] = a[j - 1]; j--; } while (j > 0 && comparator.applyAsInt(a[j - 1], tmp) > 0); a[j] = tmp; } } } private static void mergesortUsingComparator(int[] a, java.util.function.IntBinaryOperator comparator) { final int n = a.length; final int[] work = new int[n]; for (int block = 1; block <= n; block <<= 1) { final int block2 = block << 1; for (int l = 0, max = n - block; l < max; l += block2) { int m = l + block; int r = Math.min(l + block2, n); System.arraycopy(a, l, work, 0, block); for (int i = l, wi = 0, ti = m;; i++) { if (ti == r) { System.arraycopy(work, wi, a, i, block - wi); break; } if (comparator.applyAsInt(work[wi], a[ti]) > 0) { a[i] = a[ti++]; } else { a[i] = work[wi++]; if (wi == block) break; } } } } } private static final int THRESHOLD_NAIVE = 50; // private static final int THRESHOLD_DOUBLING = 0; private static int[] sais(int[] s, int upper) { int n = s.length; if (n == 0) return new int[0]; if (n == 1) return new int[] { 0 }; if (n == 2) { if (s[0] < s[1]) { return new int[] { 0, 1 }; } else { return new int[] { 1, 0 }; } } if (n < THRESHOLD_NAIVE) { return saNaive(s); } // if (n < THRESHOLD_DOUBLING) { // return saDoubling(s); // } int[] sa = new int[n]; boolean[] ls = new boolean[n]; for (int i = n - 2; i >= 0; i--) { ls[i] = s[i] == s[i + 1] ? ls[i + 1] : s[i] < s[i + 1]; } int[] sumL = new int[upper + 1]; int[] sumS = new int[upper + 1]; for (int i = 0; i < n; i++) { if (ls[i]) { sumL[s[i] + 1]++; } else { sumS[s[i]]++; } } for (int i = 0; i <= upper; i++) { sumS[i] += sumL[i]; if (i < upper) sumL[i + 1] += sumS[i]; } java.util.function.Consumer induce = lms -> { java.util.Arrays.fill(sa, -1); int[] buf = new int[upper + 1]; System.arraycopy(sumS, 0, buf, 0, upper + 1); for (int d : lms) { if (d == n) continue; sa[buf[s[d]]++] = d; } System.arraycopy(sumL, 0, buf, 0, upper + 1); sa[buf[s[n - 1]]++] = n - 1; for (int i = 0; i < n; i++) { int v = sa[i]; if (v >= 1 && !ls[v - 1]) { sa[buf[s[v - 1]]++] = v - 1; } } System.arraycopy(sumL, 0, buf, 0, upper + 1); for (int i = n - 1; i >= 0; i--) { int v = sa[i]; if (v >= 1 && ls[v - 1]) { sa[--buf[s[v - 1] + 1]] = v - 1; } } }; int[] lmsMap = new int[n + 1]; java.util.Arrays.fill(lmsMap, -1); int m = 0; for (int i = 1; i < n; i++) { if (!ls[i - 1] && ls[i]) { lmsMap[i] = m++; } } int[] lms = new int[m]; { int p = 0; for (int i = 1; i < n; i++) { if (!ls[i - 1] && ls[i]) { lms[p++] = i; } } } induce.accept(lms); if (m > 0) { int[] sortedLms = new int[m]; { int p = 0; for (int v : sa) { if (lmsMap[v] != -1) { sortedLms[p++] = v; } } } int[] recS = new int[m]; int recUpper = 0; recS[lmsMap[sortedLms[0]]] = 0; for (int i = 1; i < m; i++) { int l = sortedLms[i - 1], r = sortedLms[i]; int endL = (lmsMap[l] + 1 < m) ? lms[lmsMap[l] + 1] : n; int endR = (lmsMap[r] + 1 < m) ? lms[lmsMap[r] + 1] : n; boolean same = true; if (endL - l != endR - r) { same = false; } else { while (l < endL && s[l] == s[r]) { l++; r++; } if (l == n || s[l] != s[r]) same = false; } if (!same) { recUpper++; } recS[lmsMap[sortedLms[i]]] = recUpper; } int[] recSA = sais(recS, recUpper); for (int i = 0; i < m; i++) { sortedLms[i] = lms[recSA[i]]; } induce.accept(sortedLms); } return sa; } public static int[] suffixArray(int[] s, int upper) { assert (0 <= upper); for (int d : s) { assert (0 <= d && d <= upper); } return sais(s, upper); } public static int[] suffixArray(int[] s) { int n = s.length; int[] vals = Arrays.copyOf(s, n); java.util.Arrays.sort(vals); int p = 1; for (int i = 1; i < n; i++) { if (vals[i] != vals[i - 1]) { vals[p++] = vals[i]; } } int[] s2 = new int[n]; for (int i = 0; i < n; i++) { s2[i] = java.util.Arrays.binarySearch(vals, 0, p, s[i]); } return sais(s2, p); } public static int[] suffixArray(char[] s) { int n = s.length; int[] s2 = new int[n]; for (int i = 0; i < n; i++) { s2[i] = s[i]; } return sais(s2, 255); } public static int[] suffixArray(java.lang.String s) { return suffixArray(s.toCharArray()); } public static int[] lcpArray(int[] s, int[] sa) { int n = s.length; assert (n >= 1); int[] rnk = new int[n]; for (int i = 0; i < n; i++) { rnk[sa[i]] = i; } int[] lcp = new int[n - 1]; int h = 0; for (int i = 0; i < n; i++) { if (h > 0) h--; if (rnk[i] == 0) { continue; } int j = sa[rnk[i] - 1]; for (; j + h < n && i + h < n; h++) { if (s[j + h] != s[i + h]) break; } lcp[rnk[i] - 1] = h; } return lcp; } public static int[] lcpArray(char[] s, int[] sa) { int n = s.length; int[] s2 = new int[n]; for (int i = 0; i < n; i++) { s2[i] = s[i]; } return lcpArray(s2, sa); } public static int[] lcpArray(java.lang.String s, int[] sa) { return lcpArray(s.toCharArray(), sa); } public static int[] zAlgorithm(int[] s) { int n = s.length; if (n == 0) return new int[0]; int[] z = new int[n]; for (int i = 1, j = 0; i < n; i++) { int k = j + z[j] <= i ? 0 : Math.min(j + z[j] - i, z[i - j]); while (i + k < n && s[k] == s[i + k]) k++; z[i] = k; if (j + z[j] < i + z[i]) j = i; } z[0] = n; return z; } public static int[] zAlgorithm(char[] s) { int n = s.length; if (n == 0) return new int[0]; int[] z = new int[n]; for (int i = 1, j = 0; i < n; i++) { int k = j + z[j] <= i ? 0 : Math.min(j + z[j] - i, z[i - j]); while (i + k < n && s[k] == s[i + k]) k++; z[i] = k; if (j + z[j] < i + z[i]) j = i; } z[0] = n; return z; } public static int[] zAlgorithm(String s) { return zAlgorithm(s.toCharArray()); } } }