Problem: You are given n integers. You need to choose a subset and put the chosen numbers in a beautiful rectangle (rectangular matrix). Each chosen number should occupy one of its rectangle cells, each cell must be filled with exactly one chosen number. Some of the n numbers may not be chosen.

A rectangle (rectangular matrix) is called beautiful if in each row and in each column all values are different.

What is the largest (by the total number of cells) beautiful rectangle you can construct? Print the rectangle itself.

Input

The first line contains n (1 ≤ n ≤ 4⋅10^5). The second line contains n integers (1 ≤ a_i ≤ 10^9).

Output

In the first line print x (1 ≤ x ≤ n) — the total number of cells of the required maximum beautiful rectangle. In the second line print p and q (p ⋅ q=x): its sizes. In the next p lines print the required rectangle itself. If there are several answers, print any.

Examples

Input


12
3 1 4 1 5 9 2 6 5 3 5 8


Output


12
3 4
1 2 3 5
3 1 5 4
5 6 8 9


Input


5
1 1 1 1 1


Output


1
1 1
1

Solution (in JAVA):

Solution:
import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Collection;
import java.util.HashMap;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.Map;
import java.io.Closeable;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) throws Exception {
        Thread thread = new Thread(null, new TaskAdapter(), "", 1 << 27);
        thread.start();
        thread.join();
    }

    static class TaskAdapter implements Runnable {
        @Override
        public void run() {
            InputStream inputStream = System.in;
            OutputStream outputStream = System.out;
            FastInput in = new FastInput(inputStream);
            FastOutput out = new FastOutput(outputStream);
            CBeautifulRectangle solver = new CBeautifulRectangle();
            solver.solve(1, in, out);
            out.close();
        }
    }

    static class CBeautifulRectangle {
        public void solve(int testNumber, FastInput in, FastOutput out) {
            int n = in.readInt();
            Map<Integer, Cnt> map = new HashMap<>(n);
            for (int i = 1; i <= n; i++) {
                int a = in.readInt();
                Cnt cnt = map.get(a);
                if (cnt == null) {
                    cnt = new Cnt();
                    cnt.c = a;
                    cnt.cnt = 0;
                    map.put(a, cnt);
                }
                cnt.cnt++;
            }

            Cnt[] cnts = map.values().toArray(new Cnt[0]);
            Arrays.sort(cnts, (a, b) -> a.cnt - b.cnt);
            SimplifiedDeque<Cnt> deque = new Array2DequeAdapter<>(cnts);
            int sum = n;
            int exceed = 0;
            int mxRow = 0;
            int mxCol = 0;
            for (int i = n; i >= 1; i--) {
                while (!deque.isEmpty() && deque.peekLast().cnt > i) {
                    sum -= deque.removeLast().cnt;
                    exceed++;
                }
                int total = sum + i * exceed;
                int col = total / i;
                if (col < i) {
                    continue;
                }
                if (mxRow * mxCol < i * col) {
                    mxRow = i;
                    mxCol = col;
                }
            }

            out.println(mxRow * mxCol);
            out.append(mxRow).append(' ').append(mxCol).append('\n');

            int[][] mat = new int[mxRow][mxCol];
            for (int i = 0; i < cnts.length; i++) {
                cnts[i].cnt = Math.min(cnts[i].cnt, mxRow);
            }
            deque = new Array2DequeAdapter<>(cnts);
            for (int i = 0; i < mxCol; i++) {
                for (int j = 0; j < mxRow; j++) {
                    while (deque.peekLast().cnt == 0) {
                        deque.removeLast();
                    }
                    mat[j][i] = deque.peekLast().c;
                    deque.peekLast().cnt--;
                }
            }

            for (int i = 0; i < mxRow; i++) {
                SequenceUtils.rotate(mat[i], 0, (mxCol - i) % mxCol, mxCol - 1);
            }

            for (int i = 0; i < mxRow; i++) {
                for (int j = 0; j < mxCol; j++) {
                    out.append(mat[i][j]).append(' ');
                }
                out.println();
            }
        }

    }

    static class FastInput {
        private final InputStream is;
        private byte[] buf = new byte[1 << 13];
        private int bufLen;
        private int bufOffset;
        private int next;

        public FastInput(InputStream is) {
            this.is = is;
        }

        private int read() {
            while (bufLen == bufOffset) {
                bufOffset = 0;
                try {
                    bufLen = is.read(buf);
                } catch (IOException e) {
                    bufLen = -1;
                }
                if (bufLen == -1) {
                    return -1;
                }
            }
            return buf[bufOffset++];
        }

        public void skipBlank() {
            while (next >= 0 && next <= 32) {
                next = read();
            }
        }

        public int readInt() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            int val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

    }

    static interface SimplifiedDeque<T> extends SimplifiedStack<T> {
    }

    static class SequenceUtils {
        private static int gcd0(int a, int b) {
            return b == 0 ? a : gcd0(b, a % b);
        }

        public static void rotate(int[] list, int l, int newBeg, int r) {
            int offset = l;
            int len = r - l + 1;
            int step = len - (newBeg - l);
            int g = gcd0(newBeg, r - l + 1);
            for (int i = 0; i < g; i++) {
                int take = list[i + offset];
                int ni = i;
                while ((ni = (ni + step) % len) != i) {
                    int tmp = list[ni + offset];
                    list[ni + offset] = take;
                    take = tmp;
                }
                list[i + offset] = take;
            }
        }

    }

    static class FastOutput implements AutoCloseable, Closeable {
        private StringBuilder cache = new StringBuilder(10 << 20);
        private final Writer os;

        public FastOutput(Writer os) {
            this.os = os;
        }

        public FastOutput(OutputStream os) {
            this(new OutputStreamWriter(os));
        }

        public FastOutput append(char c) {
            cache.append(c);
            return this;
        }

        public FastOutput append(int c) {
            cache.append(c);
            return this;
        }

        public FastOutput println(int c) {
            cache.append(c).append('\n');
            return this;
        }

        public FastOutput println() {
            cache.append('\n');
            return this;
        }

        public FastOutput flush() {
            try {
                os.append(cache);
                os.flush();
                cache.setLength(0);
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
            return this;
        }

        public void close() {
            flush();
            try {
                os.close();
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        }

        public String toString() {
            return cache.toString();
        }

    }

    static class Cnt {
        int c;
        int cnt;

    }

    static interface SimplifiedStack<T> extends Iterable<T> {
        boolean isEmpty();

        T peekLast();

        T removeLast();

    }

    static class Array2DequeAdapter<T> implements SimplifiedDeque<T> {
        T[] data;
        int l;
        int r;

        public Array2DequeAdapter(T[] data) {
            this(data, 0, data.length - 1);
        }

        public Array2DequeAdapter(T[] data, int l, int r) {
            this.data = data;
            this.l = l;
            this.r = r;
        }

        public boolean isEmpty() {
            return l > r;
        }

        public T peekLast() {
            return data[r];
        }

        public T removeLast() {
            return data[r--];
        }

        public Iterator<T> iterator() {
            return new Iterator<T>() {
                int iter = l;


                public boolean hasNext() {
                    return iter <= r;
                }


                public T next() {
                    return data[iter++];
                }
            };
        }

    }
}