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
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;


import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map.Entry;
import java.util.Random;
import java.util.TreeSet;

public final class CF_606_D2_F
{


	static boolean verb=true;
	static void log(Object X){if (verb) System.err.println(X);}
	static void log(Object[] X){if (verb) {for (Object U:X) System.err.print(U+" ");System.err.println("");}}
	static void log(int[] X){if (verb) {for (int U:X) System.err.print(U+" ");System.err.println("");}}
	static void log(int[] X,int L){if (verb) {for (int i=0;i<L;i++) System.err.print(X[i]+" ");System.err.println("");}}
	static void log(long[] X){if (verb) {for (long U:X) System.err.print(U+" ");System.err.println("");}}

	static void logWln(Object X){if (verb) System.err.print(X);}
	static void info(Object o){	System.out.println(o);}
	static void output(Object o){outputWln(""+o+"\n");	}
	static void outputWln(Object o){try {out.write(""+ o);} catch (Exception e) {}}












	static long mod=1000000007;

	// Global vars
	static BufferedWriter out;
	static InputReader reader;




	static void test() {
		log("testing");

		log("done");

	}

	static class Composite implements Comparable<Composite>{
		int v;
		int num;

		public int compareTo(Composite X) {
			if (num!=X.num)
				return num-X.num;
			return v-X.v;
		}

		public Composite(int v, int num) {
			this.v = v;
			this.num = num;
		}



	}


	static void process() throws Exception {


		//String bob=")))aaa(R(RaR))R(R(a)))RRaLaa)LRaa(aR))(LaRR(a(a)LaR()R(RR)(RaRa(()aaLLLLL(a)(()R(()LRaaL(L()L))aLa)aaR()R)()L)(RLRa)L()R)RRL)LL)R)aaR()a)RR)aRL())R)R(aL)))R(a(RR)L(Raa)RL)aR(LLaRR(LaLR(L((a(aaRL))aa)RR()LRL)aaa))aaaLaRLLaaa)aa())R)aaL(()a)(aR(LRaR(a)a((aLL(L)RLL)a)(a)LL(LLR)(R((a(()a(LRL(()LRRaaRLLRaR()RR(a(R)a((((L(Raa)aa())a(a(R(aR)L))Ra()RLRL)(L)RaL)LaaaRaR))a)Ra)LL))((aR))LL)(L()R))L(aaR(LRRRaL)L(LaLR)L))RR((aaaL)((L()aL)La(a(R)(aR((RLaLaR)RaRL)))aRaL))RR)L)(()()LaLRaR)((aaaLa)R)aL(RR(Ra(RRaRR";
		//log(bob.length());

		//arrayTest();

		out = new BufferedWriter(new OutputStreamWriter(System.out));
		reader = new InputReader(System.in);

		int n=reader.readInt();

		HashMap<Integer,Integer> hm=new HashMap<Integer,Integer>();
		int idx=0;

		int[] a=new int[n];
		int[] mem=new int[n];
		int[] prev=new int[n];
		for (int i=0;i<n;i++) {
			int x=reader.readInt();
			Integer bob=hm.get(x);
			if (bob==null) {
				bob=idx++;
				hm.put(x,bob);
				prev[bob]=x;
			}
			a[i]=bob;
			mem[bob]++;
		}

		ArrayList<Composite> lst=new ArrayList<Composite>();

		for (int u=0;u<n;u++) {
			if (mem[u]!=0) {
				lst.add(new Composite(u,mem[u]));
			}
		}
		Collections.sort(lst);

		int L=lst.size();
		//log("L:"+L);

		// let b be the biggest dimension
		int start=-1;
		int sum=0;
		int best=0;
		int tu=0;
		int tv=0;
		int tb=0;
		for (int b=1;b<=n;b++) {
			// we can integrate all the ones below b
			// and for the other, we have maximum b occurences
			while (start+1<L && lst.get(start+1).num<=b) {
				start++;
				sum+=lst.get(start).num;
			}
			int tot=0;
			int oc=start+1;
			tot+=sum;
			tot+=(L-oc)*b;
			//log("b:"+b+" tot:"+tot);
			//log("b:"+b+"sum:"+sum+" rem:"+(L-sum)+" tot:"+tot);
			// so now we have tot
			// we need to find the minimum rectange doing <=tot
			for (int c=b;c<=tot/c;c++) {
				if (tot/c>=b) {
					int nb=tot-tot%c;
					if (nb>best) {
						best=nb;
						tu=c;
						tv=tot/c;
						tb=b;
					}
				}
				
			}
		}
		output(best);
		if (tu>tv) {
			int z=tu;
			tu=tv;
			tv=z;
		}
		output(tu+" "+tv);
		int[][] map=new int[tu][tv];
		int st=L-1;
		int cnt=0;
		for (int delta=0;delta<tv;delta++) {
			for (int u=0;u<tu;u++) {
				int x=lst.get(st).v;
				map[u][(u+delta)%tv]=prev[x];
				cnt++;
				if (cnt==tb || cnt==lst.get(st).num) {
					st--;
					cnt=0;
				}
			}
		}
		for (int u=0;u<tu;u++) {
			for (int v=0;v<tv;v++) {
				outputWln(map[u][v]+" ");
			}
			output("");
		}


		try {
			out.close();
		} catch (Exception e) {
		}

	}





	public static void main(String[] args) throws Exception {
		process();

	}

	static final class InputReader {
		private final InputStream stream;
		private final byte[] buf = new byte[1024];
		private int curChar;
		private int numChars;

		public InputReader(InputStream stream) {
			this.stream = stream;
		}

		private int read() throws IOException {
			if (curChar >= numChars) {
				curChar = 0;
				numChars = stream.read(buf);
				if (numChars <= 0) {
					return -1;
				}
			}
			return buf[curChar++];
		}

		public final String readString() throws IOException {
			int c = read();
			while (isSpaceChar(c)) {
				c = read();
			}
			StringBuilder res = new StringBuilder();
			do {
				res.append((char) c);
				c = read();
			} while (!isSpaceChar(c));
			return res.toString();
		}

		public final String readString(int L) throws IOException {
			int c = read();
			while (isSpaceChar(c)) {
				c = read();
			}
			StringBuilder res = new StringBuilder(L);
			do {
				res.append((char) c);
				c = read();
			} while (!isSpaceChar(c));
			return res.toString();
		}

		public final int readInt() throws IOException {
			int c = read();
			boolean neg = false;
			while (isSpaceChar(c)) {
				c = read();
			}
			char d = (char) c;
			// log("d:"+d);
			if (d == '-') {
				neg = true;
				c = read();
			}
			int res = 0;
			do {
				res *= 10;
				res += c - '0';
				c = read();
			} while (!isSpaceChar(c));
			// log("res:"+res);
			if (neg)
				return -res;
			return res;

		}

		public final long readLong() throws IOException {
			int c = read();
			boolean neg = false;
			while (isSpaceChar(c)) {
				c = read();
			}
			char d = (char) c;
			// log("d:"+d);
			if (d == '-') {
				neg = true;
				c = read();
			}
			long res = 0;
			do {
				res *= 10;
				res += c - '0';
				c = read();
			} while (!isSpaceChar(c));
			// log("res:"+res);
			if (neg)
				return -res;
			return res;

		}

		private boolean isSpaceChar(int c) {
			return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
		}
	}

}