#include <bits/stdc++.h>

using namespace std;

int main() {
   ios_base::sync_with_stdio(false);
   int N;
   cin >> N;
   unordered_map<int, int> cnt;
   for (int i = 0; i < N; ++i) {
      int x;
      cin >> x;
      ++cnt[x];
   }
   vector<int> pref(N + 1);
   vector<int> suff(N + 1);
   for (auto p : cnt) {
      pref[p.second] += p.second;
      suff[p.second] += 1;
   }
   for (int i = 1; i <= N; ++i) {
      pref[i] += pref[i - 1];
   }
   for (int i = N - 1; i >= 0; --i) {
      suff[i] += suff[i + 1];
   }
   int bestP = 0;
   int bestS = 0;
   for (int curP = 1; curP <= N; ++curP) {
      int curS = pref[curP - 1] + curP * suff[curP];
      int curQ = curS / curP;
      if (curQ < curP) {
         continue;
      }
      curS = curP * curQ;
      if (curS > bestS) {
         bestP = curP;
         bestS = curS;
      }
   }
   int bestQ = bestS / bestP;
   vector<int> valsMore;
   vector<int> valsLess;
   for (auto p : cnt) {
      if (p.second >= bestP) {
         int curCnt = bestP;
         while (curCnt--) {
            valsMore.emplace_back(p.first);
         }
      } else {
         int curCnt = p.second;
         while (curCnt--) {
            valsLess.emplace_back(p.first);
         }
      }
   }
   for (int v : valsLess) {
      valsMore.emplace_back(v);
   }
   vector<vector<int>> ans(bestP, vector<int>(bestQ));
   for (int diag = 0; diag < bestQ; ++diag) {
      for (int z = 0; z < bestP; ++z) {
         ans[z][(diag + z) % bestQ] = valsMore[diag * bestP + z];
      }
   }
   cout << bestS << "\n" << bestP << " " << bestQ << "\n";
   for (auto vv : ans) {
      for (int v : vv) {
         cout << v << " ";
      }
      cout << "\n";
   }
   return 0;
}


#include <bits/stdc++.h>

using namespace std;

int main() {
   ios_base::sync_with_stdio(false);
   int N;
   cin >> N;
   map<int, int> cnt;
   for (int i = 0; i < N; ++i) {
      int x;
      cin >> x;
      ++cnt[x];
   }
   vector<int> pref(N + 1);
   vector<int> suff(N + 1);
   for (auto p : cnt) {
      pref[p.second] += p.second;
      suff[p.second] += 1;
   }
   for (int i = 1; i <= N; ++i) {
      pref[i] += pref[i - 1];
   }
   for (int i = N - 1; i >= 0; --i) {
      suff[i] += suff[i + 1];
   }
   int bestP = 0;
   int bestS = 0;
   for (int curP = 1; curP <= N; ++curP) {
      int curS = pref[curP - 1] + curP * suff[curP];
      int curQ = curS / curP;
      if (curQ < curP) {
         continue;
      }
      curS = curP * curQ;
      if (curS > bestS) {
         bestP = curP;
         bestS = curS;
      }
   }
   int bestQ = bestS / bestP;
   vector<int> vals;
   for (auto p : cnt) {
      int curCnt = min(bestP, p.second);
      while (curCnt--) {
         vals.emplace_back(p.first);
      }
   }
   vals.resize(bestS);
   vector<vector<int>> ans(bestP, vector<int>(bestQ));
   for (int diag = 0; diag < bestQ; ++diag) {
      for (int z = 0; z < bestP; ++z) {
         ans[z][(diag + z) % bestQ] = vals[diag * bestP + z];
      }
   }
   cout << bestS << "\n" << bestP << " " << bestQ << "\n";
   for (auto vv : ans) {
      for (int v : vv) {
         cout << v << " ";
      }
      cout << "\n";
   }
   return 0;
}


#include <bits/stdc++.h>

using namespace std;

int main() {
   ios_base::sync_with_stdio(false);
   int N;
   cin >> N;
   map<int, int> cnt;
   for (int i = 0; i < N; ++i) {
      int x;
      cin >> x;
      ++cnt[x];
   }
   vector<int> pref(N + 1);
   vector<int> suff(N + 1);
   for (auto p : cnt) {
      pref[p.second] += p.second;
      suff[p.second] += 1;
   }
   for (int i = 1; i <= N; ++i) {
      pref[i] += pref[i - 1];
   }
   for (int i = N - 1; i >= 0; --i) {
      suff[i] += suff[i + 1];
   }
   int bestP = 0;
   int bestS = 0;
   for (int curP = 1; curP <= N; ++curP) {
      int curS = pref[curP - 1] + curP * suff[curP];
      int curQ = curS / curP;
      if (curQ < curP) {
         continue;
      }
      curS = curP * curQ;
      if (curS > bestS) {
         bestP = curP;
         bestS = curS;
      }
   }
   int bestQ = bestS / bestP;
   vector<int> vals;
   for (auto p : cnt) {
      int curCnt = min(bestP, p.second);
      while (curCnt--) {
         vals.emplace_back(p.first);
      }
   }
   vals.resize(bestS);
   vector<vector<int>> ans(bestP, vector<int>(bestQ));
   for (int diag = 0; diag < bestQ; ++diag) {
      for (int z = 0; z < bestP; ++z) {
         ans[z][(diag + z) % bestQ] = vals[diag * bestP + z];
      }
   }
   for (int row = 0; row < bestP; ++row) {
      set<int> st;
      for (int z = 0; z < bestQ; ++z) {
         st.emplace(ans[row][z]);
      }
      assert(st.size() == bestQ);
   }
   for (int col = 0; col < bestQ; ++col) {
      set<int> st;
      for (int z = 0; z < bestP; ++z) {
         st.emplace(ans[z][col]);
      }
      assert(st.size() == bestP);
   }
   cout << bestS << "\n" << bestP << " " << bestQ << "\n";
   for (auto vv : ans) {
      for (int v : vv) {
         cout << v << " ";
      }
      cout << "\n";
   }
   return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define F first
#define S second
#define R cin>>
#define Z class
#define ll long long
#define ln cout<<'\n'
#define in(a) insert(a)
#define pb(a) push_back(a)
#define pd(a) printf("%.10f\n",a)
#define mem(a) memset(a,0,sizeof(a))
#define all(c) (c).begin(),(c).end()
#define iter(c) __typeof((c).begin())
#define rrep(i,n) for(ll i=(ll)(n)-1;i>=0;i--)
#define REP(i,m,n) for(ll i=(ll)(m);i<(ll)(n);i++)
#define rep(i,n) REP(i,0,n)
#define tr(it,c) for(iter(c) it=(c).begin();it!=(c).end();it++)
template<Z A>void pr(A a){cout<<a;ln;}
template<Z A,Z B>void pr(A a,B b){cout<<a<<' ';pr(b);}
template<Z A,Z B,Z C>void pr(A a,B b,C c){cout<<a<<' ';pr(b,c);}
template<Z A,Z B,Z C,Z D>void pr(A a,B b,C c,D d){cout<<a<<' ';pr(b,c,d);}
template<Z A>void PR(A a,ll n){rep(i,n){if(i)cout<<' ';cout<<a[i];}ln;}
ll check(ll n,ll m,ll x,ll y){return x>=0&&x<n&&y>=0&&y<m;}
const ll MAX=1e9+7,MAXL=1LL<<61,dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
typedef pair<ll,ll> P;

void Main() {
  ll n;
  cin >> n;
  ll a[n];
  rep(i,n) cin >> a[i];
  map<ll,ll> m;
  rep(i,n) m[a[i]]++;
  priority_queue<P> que;
  tr(it,m) que.push(P(it->S,it->F));
  ll ans=0,k=0,nn=n,n1,m1;
  while(!que.empty()) {
    ll t=que.top().F;
    ll d=0,n2,m2;
    for(ll i=1; i*i<=n; i++) {
      if(n%i) continue;
      ll j=n/i;
      if(i>=t&&j>=t) {
        if(d<i*j) {
          d=i*j;
          n2=i;
          m2=j;
        }
      }
    }
    if(d>ans) {
      ans=d;
      k=n;
      n1=n2;
      m1=m2;
    }
    P p=que.top();que.pop();
    m[p.S]--;
    p.F--;
    if(p.F) que.push(p);
    n--;
  }
  m.clear();
  rep(i,nn) m[a[i]]++;
  tr(it,m) que.push(P(it->S,it->F));
  while(!que.empty()&&nn>k) {
    P p=que.top();que.pop();
    m[p.S]--;
    p.F--;
    if(p.F) que.push(p);
    nn--;
  }
  vector<ll> v;
  tr(it,m) {
    rep(i,it->S) v.pb(it->F);
  }
  ll d[n1][m1];
  mem(d);
  int x=0,y=0;
  rep(i,v.size()) {
    d[x][y]=v[i];
    x++,y++;
    x%=n1;
    y%=m1;
    if(d[x][y]) {
      y++;
      y%=m1;
    }
  }
  pr(ans);
  pr(n1,m1);
  rep(i,n1) PR(d[i],m1);
}

int main(){ios::sync_with_stdio(0);cin.tie(0);Main();return 0;}


#include <bits/stdc++.h>
using namespace std;
#define F first
#define S second
#define R cin>>
#define Z class
#define ll long long
#define ln cout<<'\n'
#define in(a) insert(a)
#define pb(a) push_back(a)
#define pd(a) printf("%.10f\n",a)
#define mem(a) memset(a,0,sizeof(a))
#define all(c) (c).begin(),(c).end()
#define iter(c) __typeof((c).begin())
#define rrep(i,n) for(ll i=(ll)(n)-1;i>=0;i--)
#define REP(i,m,n) for(ll i=(ll)(m);i<(ll)(n);i++)
#define rep(i,n) REP(i,0,n)
#define tr(it,c) for(iter(c) it=(c).begin();it!=(c).end();it++)
template<Z A>void pr(A a){cout<<a;ln;}
template<Z A,Z B>void pr(A a,B b){cout<<a<<' ';pr(b);}
template<Z A,Z B,Z C>void pr(A a,B b,C c){cout<<a<<' ';pr(b,c);}
template<Z A,Z B,Z C,Z D>void pr(A a,B b,C c,D d){cout<<a<<' ';pr(b,c,d);}
template<Z A>void PR(A a,ll n){rep(i,n){if(i)cout<<' ';cout<<a[i];}ln;}
ll check(ll n,ll m,ll x,ll y){return x>=0&&x<n&&y>=0&&y<m;}
const ll MAX=1e9+7,MAXL=1LL<<61,dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
typedef pair<ll,ll> P;

void Main() {
  ll n;
  cin >> n;
  ll a[n];
  rep(i,n) cin >> a[i];
  map<ll,ll> m;
  rep(i,n) m[a[i]]++;
  priority_queue<P> que;
  tr(it,m) que.push(P(it->S,it->F));
  ll ans=0,k=0,nn=n,n1,m1;
  while(!que.empty()) {
    ll t=que.top().F;
    ll d=0,n2,m2;
    for(ll i=1; i*i<=n; i++) {
      if(n%i) continue;
      ll j=n/i;
      if(i>=t&&j>=t) {
        if(d<i*j) {
          d=i*j;
          n2=i;
          m2=j;
        }
      }
    }
    if(d>ans) {
      ans=d;
      k=n;
      n1=n2;
      m1=m2;
    }
    P p=que.top();que.pop();
    m[p.S]--;
    p.F--;
    if(p.F) que.push(p);
    n--;
  }
  m.clear();
  rep(i,nn) m[a[i]]++;
  tr(it,m) que.push(P(it->S,it->F));
  while(!que.empty()&&nn>k) {
    P p=que.top();que.pop();
    m[p.S]--;
    p.F--;
    if(p.F) que.push(p);
    nn--;
  }
  vector<ll> v;
  vector<P> g;
  tr(it,m) g.pb(P(it->S,it->F));
  sort(all(g),greater<P>());
  rep(i,g.size()) {
    rep(j,g[i].F) v.pb(g[i].S);
  }
  ll d[n1][m1];
  mem(d);
  int x=0,y=0;
  rep(i,v.size()) {
    d[x][y]=v[i];
    x++,y++;
    x%=n1;
    y%=m1;
    if(d[x][y]) {
      y++;
      y%=m1;
    }
  }
  pr(ans);
  pr(n1,m1);
  rep(i,n1) PR(d[i],m1);
}

int main(){ios::sync_with_stdio(0);cin.tie(0);Main();return 0;}


#include <bits/stdc++.h>
using namespace std;
#define F first
#define S second
#define R cin>>
#define Z class
#define ll long long
#define ln cout<<'\n'
#define in(a) insert(a)
#define pb(a) push_back(a)
#define pd(a) printf("%.10f\n",a)
#define mem(a) memset(a,0,sizeof(a))
#define all(c) (c).begin(),(c).end()
#define iter(c) __typeof((c).begin())
#define rrep(i,n) for(ll i=(ll)(n)-1;i>=0;i--)
#define REP(i,m,n) for(ll i=(ll)(m);i<(ll)(n);i++)
#define rep(i,n) REP(i,0,n)
#define tr(it,c) for(iter(c) it=(c).begin();it!=(c).end();it++)
template<Z A>void pr(A a){cout<<a;ln;}
template<Z A,Z B>void pr(A a,B b){cout<<a<<' ';pr(b);}
template<Z A,Z B,Z C>void pr(A a,B b,C c){cout<<a<<' ';pr(b,c);}
template<Z A,Z B,Z C,Z D>void pr(A a,B b,C c,D d){cout<<a<<' ';pr(b,c,d);}
template<Z A>void PR(A a,ll n){rep(i,n){if(i)cout<<' ';cout<<a[i];}ln;}
ll check(ll n,ll m,ll x,ll y){return x>=0&&x<n&&y>=0&&y<m;}
const ll MAX=1e9+7,MAXL=1LL<<61,dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
typedef pair<ll,ll> P;

void Main() {
  ll e[555555];
  mem(e);
  for(ll i=1; i<555555; i++) {
    for(ll j=i; j<555555; j+=i) {
      ll k=j/i;
      e[j]=max(e[j],min(i,k));
    }
  }
  ll n;
  cin >> n;
  ll a[n];
  rep(i,n) cin >> a[i];
  map<ll,ll> m;
  rep(i,n) m[a[i]]++;
  priority_queue<P> que;
  tr(it,m) que.push(P(it->S,it->F));
  ll ans=0,k=0,nn=n,n1,m1;
  while(!que.empty()) {
    ll t=que.top().F;
    ll d=0,n2,m2;
    ll i=e[n];
    ll j=n/e[n];
    if(i>=t&&j>=t) {
      if(d<i*j) {
        d=i*j;
        n2=i;
        m2=j;
      }
    }
    if(d>ans) {
      ans=d;
      k=n;
      n1=n2;
      m1=m2;
    }
    P p=que.top();que.pop();
    m[p.S]--;
    p.F--;
    if(p.F) que.push(p);
    n--;
  }
  m.clear();
  rep(i,nn) m[a[i]]++;
  tr(it,m) que.push(P(it->S,it->F));
  while(!que.empty()&&nn>k) {
    P p=que.top();que.pop();
    m[p.S]--;
    p.F--;
    if(p.F) que.push(p);
    nn--;
  }
  vector<ll> v;
  vector<P> g;
  tr(it,m) g.pb(P(it->S,it->F));
  sort(all(g),greater<P>());
  rep(i,g.size()) {
    rep(j,g[i].F) v.pb(g[i].S);
  }
  ll d[n1][m1];
  mem(d);
  int x=0,y=0;
  rep(i,v.size()) {
    d[x][y]=v[i];
    x++,y++;
    x%=n1;
    y%=m1;
    if(d[x][y]) {
      y++;
      y%=m1;
    }
  }
  pr(ans);
  pr(n1,m1);
  rep(i,n1) PR(d[i],m1);
}

int main(){ios::sync_with_stdio(0);cin.tie(0);Main();return 0;}


#include <bits/stdc++.h>
using namespace std;
#define F first
#define S second
#define R cin>>
#define Z class
#define ll long long
#define ln cout<<'\n'
#define in(a) insert(a)
#define pb(a) push_back(a)
#define pd(a) printf("%.10f\n",a)
#define mem(a) memset(a,0,sizeof(a))
#define all(c) (c).begin(),(c).end()
#define iter(c) __typeof((c).begin())
#define rrep(i,n) for(ll i=(ll)(n)-1;i>=0;i--)
#define REP(i,m,n) for(ll i=(ll)(m);i<(ll)(n);i++)
#define rep(i,n) REP(i,0,n)
#define tr(it,c) for(iter(c) it=(c).begin();it!=(c).end();it++)
template<Z A>void pr(A a){cout<<a;ln;}
template<Z A,Z B>void pr(A a,B b){cout<<a<<' ';pr(b);}
template<Z A,Z B,Z C>void pr(A a,B b,C c){cout<<a<<' ';pr(b,c);}
template<Z A,Z B,Z C,Z D>void pr(A a,B b,C c,D d){cout<<a<<' ';pr(b,c,d);}
template<Z A>void PR(A a,ll n){rep(i,n){if(i)cout<<' ';cout<<a[i];}ln;}
ll check(ll n,ll m,ll x,ll y){return x>=0&&x<n&&y>=0&&y<m;}
const ll MAX=1e9+7,MAXL=1LL<<61,dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
typedef pair<ll,ll> P;

void Main() {
  ll e[555555];
  mem(e);
  for(ll i=1; i<55; i++) {
    for(ll j=i; j<55; j+=i) {
      ll k=j/i;
      e[j]=max(e[j],min(i,k));
    }
  }
  ll n;
  cin >> n;
  ll a[n];
  rep(i,n) cin >> a[i];
  map<ll,ll> m;
  rep(i,n) m[a[i]]++;
  priority_queue<P> que;
  tr(it,m) que.push(P(it->S,it->F));
  ll ans=0,k=0,nn=n,n1,m1;
  while(!que.empty()) {
    ll t=que.top().F;
    ll d=0,n2,m2;
    ll i=e[n];
    ll j=n/e[n];
    if(i>=t&&j>=t) {
      if(d<i*j) {
        d=i*j;
        n2=i;
        m2=j;
      }
    }
    /*
    for(ll i=1; i*i<=n; i++) {
      if(n%i) continue;
      ll j=n/i;
      if(i>=t&&j>=t) {
        if(d<i*j) {
          d=i*j;
          n2=i;
          m2=j;
        }
      }
    }
    */
    if(d>ans) {
      ans=d;
      k=n;
      n1=n2;
      m1=m2;
    }
    P p=que.top();que.pop();
    m[p.S]--;
    p.F--;
    if(p.F) que.push(p);
    n--;
  }
  m.clear();
  rep(i,nn) m[a[i]]++;
  tr(it,m) que.push(P(it->S,it->F));
  while(!que.empty()&&nn>k) {
    P p=que.top();que.pop();
    m[p.S]--;
    p.F--;
    if(p.F) que.push(p);
    nn--;
  }
  vector<ll> v;
  vector<P> g;
  tr(it,m) g.pb(P(it->S,it->F));
  sort(all(g),greater<P>());
  rep(i,g.size()) {
    rep(j,g[i].F) v.pb(g[i].S);
  }
  ll d[n1][m1];
  mem(d);
  int x=0,y=0;
  rep(i,v.size()) {
    d[x][y]=v[i];
    x++,y++;
    x%=n1;
    y%=m1;
    if(d[x][y]) {
      y++;
      y%=m1;
    }
  }
  pr(ans);
  pr(n1,m1);
  rep(i,n1) PR(d[i],m1);
}

int main(){ios::sync_with_stdio(0);cin.tie(0);Main();return 0;}


#include <bits/stdc++.h>

using namespace std;

#define _ ios_base::sync_with_stdio(0);cin.tie(0);
#define endl '\n'

typedef long long ll;
typedef pair<int, int> ii;

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;

map<int, int> cmp;
map<int, int> back_cmp;

void compress(vector<int> &a){
	for (int &i : a){
		auto it = cmp.find(i);
		if (it != cmp.end()) continue;
		int sz = cmp.size();
		cmp[i] = sz;
		back_cmp[sz] = i;
	}
}

int main(){ _
	int n; cin >> n;;
	vector<int>	a(n);
	for (auto &it : a) cin >> it;
	compress(a);
	for (auto &it : a) it = cmp[it];

	set<int> el(a.begin(), a.end());

	vector<int> freq(n+1, 0);
	for (int i : a)
		freq[i]++;

	vector<int> aux(n+1, 0);
	for (auto i : el) aux[freq[i]]++;

	vector<int> gr(n+1, 0);
	for (int i = n-1; i >= 0; i--)
		gr[i] = gr[i+1] + aux[i+1];

	vector<ll> sum(n+1, 0);
	for (int i = 1; i <= n; i++){
		sum[i] = sum[i-1] + i*aux[i];
	}

	vector<ll> av(n+1, 0);
	for (int i = 1; i <= n; i++){
		av[i] = sum[i] + gr[i]*i;
	}

	auto bb = [&](int h){
		int ans = 0;
		int l = 0, r = n;
		while (l <= r){
			int w = (l+r)/2;
			int lim = min(h, w);
			if (ll(h)*ll(w) <= av[lim]){
				ans = max(ans, w);
				l = w+1;
			}
			else r = w-1;
		}
		return ans;
	};

	ll h = 1, w = 1;
	for (int i = 1; i <= n; i++){
		ll H = i, W = bb(i);
		if (W*H > w*h){
			w = W;
			h = H;
		}
	}

	auto fix = [&](int I, int J){
		return make_pair(I%h, J%w);
	};
	vector<ii> order;
	for (int j = 0; j < w; j++){
		for (int i = 0; i < h; i++){
			order.push_back(fix(i, j+i));
		}
	}

	vector<vector<int>> p(h, vector<int>(w));
	vector<ii> repo;
	for (int i : el){
		int lim = min(freq[i], int(w));
		repo.push_back({lim, i});
	}
	sort(repo.begin(), repo.end(), greater<ii>());
	auto iter = repo.begin();
	auto next = [&](){
		if (iter->first == 0) iter++;
		iter->first--;
		return iter->second;
	};
	for (auto it : order){
		int i, j;
		tie(i, j) = it;
		p[i][j] = next();
	}
	cout << h*w << endl;
	cout << h << " " << w << endl;
	for (int i = 0; i < h; i++){
		for (int j = 0; j < w; j++)
			cout << back_cmp[p[i][j]] << " ";
		cout << endl;
	}

	exit(0);
}


#include <bits/stdc++.h>

using namespace std;

#define _ ios_base::sync_with_stdio(0);cin.tie(0);
#define endl '\n'

typedef long long ll;
typedef pair<int, int> ii;

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;

map<int, int> cmp;
map<int, int> back_cmp;

void compress(vector<int> &a){
	for (int &i : a){
		auto it = cmp.find(i);
		if (it != cmp.end()) continue;
		int sz = cmp.size();
		cmp[i] = sz;
		back_cmp[sz] = i;
	}
}

int main(){ _
	int n; cin >> n;;
	vector<int>	a(n);
	for (auto &it : a) cin >> it;
	compress(a);
	for (auto &it : a) it = cmp[it];

	set<int> el(a.begin(), a.end());

	vector<int> freq(n+1, 0);
	for (int i : a)
		freq[i]++;

	vector<int> aux(n+1, 0);
	for (auto i : el) aux[freq[i]]++;

	vector<int> gr(n+1, 0);
	for (int i = n-1; i >= 0; i--)
		gr[i] = gr[i+1] + aux[i+1];

	vector<ll> sum(n+1, 0);
	for (int i = 1; i <= n; i++){
		sum[i] = sum[i-1] + i*aux[i];
	}

	vector<ll> av(n+1, 0);
	for (int i = 1; i <= n; i++){
		av[i] = sum[i] + gr[i]*i;
	}

	auto bb = [&](int h){
		int ans = 0;
		int l = 0, r = n;
		while (l <= r){
			int w = (l+r)/2;
			int lim = min(h, w);
			if (ll(h)*ll(w) <= av[lim]){
				ans = max(ans, w);
				l = w+1;
			}
			else r = w-1;
		}
		return ans;
	};

	ll h = 1, w = 1;
	for (int i = 1; i <= n; i++){
		ll H = i, W = bb(i);
		if (W*H > w*h){
			w = W;
			h = H;
		}
	}

	auto fix = [&](int I, int J){
		return make_pair(I%h, J%w);
	};
	vector<ii> order;
	for (int j = 0; j < w; j++){
		for (int i = 0; i < h; i++){
			order.push_back(fix(i, j+i));
		}
	}

	vector<vector<int>> p(h, vector<int>(w));
	vector<ii> repo;
	for (int i : el){
		int lim = min(freq[i], int(h));
		repo.push_back({lim, i});
	}
	sort(repo.begin(), repo.end(), greater<ii>());
	auto iter = repo.begin();
	auto next = [&](){
		if (iter->first == 0) iter++;
		iter->first--;
		return iter->second;
	};

	for (auto it : order){
		int i, j;
		tie(i, j) = it;
		p[i][j] = next();
	}
	cout << h*w << endl;
	cout << h << " " << w << endl;
	for (int i = 0; i < h; i++){
		for (int j = 0; j < w; j++)
			cout << back_cmp[p[i][j]] << " ";
		cout << endl;
	}

	exit(0);
}


#include <bits/stdc++.h>

using namespace std;

#define _ ios_base::sync_with_stdio(0);cin.tie(0);
#define endl '\n'

typedef long long ll;
typedef pair<int, int> ii;

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;

map<int, int> cmp;
map<int, int> back_cmp;

void compress(vector<int> &a){
	for (int &i : a){
		auto it = cmp.find(i);
		if (it != cmp.end()) continue;
		int sz = cmp.size();
		cmp[i] = sz;
		back_cmp[sz] = i;
	}
}

int main(){ _
	int n; cin >> n;;
	vector<int>	a(n);
	for (auto &it : a) cin >> it;
	compress(a);
	for (auto &it : a) it = cmp[it];

	set<int> el(a.begin(), a.end());

	vector<int> freq(n+1, 0);
	for (int i : a)
		freq[i]++;

	vector<int> aux(n+1, 0);
	for (auto i : el) aux[freq[i]]++;

	vector<int> gr(n+1, 0);
	for (int i = n-1; i >= 0; i--)
		gr[i] = gr[i+1] + aux[i+1];

	vector<ll> sum(n+1, 0);
	for (int i = 1; i <= n; i++){
		sum[i] = sum[i-1] + i*aux[i];
	}

	vector<ll> av(n+1, 0);
	for (int i = 1; i <= n; i++){
		av[i] = sum[i] + gr[i]*i;
	}

	auto bb = [&](int h){
		int ans = 0;
		int l = 0, r = n;
		while (l <= r){
			int w = l;
			int lim = min(h, w);
			if (ll(h)*ll(w) <= av[lim]){
				ans = max(ans, w);
			}
			l++;
		}
		return ans;
	};

	ll h = 1, w = 1;
	for (int i = 1; i*i <= n; i++){
		ll H = i, W = bb(i);
		if (W*H > w*h){
			w = W;
			h = H;
		}
	}

	auto fix = [&](int I, int J){
		return make_pair(I%h, J%w);
	};
	vector<ii> order;
	for (int j = 0; j < w; j++){
		for (int i = 0; i < h; i++){
			order.push_back(fix(i, j+i));
		}
	}

	vector<vector<int>> p(h, vector<int>(w));
	vector<ii> repo;
	for (int i : el){
		int lim = min(freq[i], int(w));
		repo.push_back({lim, i});
	}
	sort(repo.begin(), repo.end(), greater<ii>());
	auto iter = repo.begin();
	auto next = [&](){
		if (iter->first == 0) iter++;
		iter->first--;
		return iter->second;
	};
	for (auto it : order){
		int i, j;
		tie(i, j) = it;
		p[i][j] = next();
	}
	cout << h*w << endl;
	cout << h << " " << w << endl;
	for (int i = 0; i < h; i++){
		for (int j = 0; j < w; j++)
			cout << back_cmp[p[i][j]] << " ";
		cout << endl;
	}

	exit(0);
}


#include <bits/stdc++.h>

using namespace std;

#define _ ios_base::sync_with_stdio(0);cin.tie(0);
#define endl '\n'

typedef long long ll;
typedef pair<int, int> ii;

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;

map<int, int> cmp;
map<int, int> back_cmp;

void compress(vector<int> &a){
	for (int &i : a){
		auto it = cmp.find(i);
		if (it != cmp.end()) continue;
		int sz = cmp.size();
		cmp[i] = sz;
		back_cmp[sz] = i;
	}
}

int main(){ _
	int n; cin >> n;;
	vector<int>	a(n);
	for (auto &it : a) cin >> it;
	compress(a);
	for (auto &it : a) it = cmp[it];

	set<int> el(a.begin(), a.end());

	vector<int> freq(n+1, 0);
	for (int i : a)
		freq[i]++;

	vector<int> aux(n+1, 0);
	for (auto i : el) aux[freq[i]]++;

	vector<int> gr(n+1, 0);
	for (int i = n-1; i >= 0; i--)
		gr[i] = gr[i+1] + aux[i+1];

	vector<ll> sum(n+1, 0);
	for (int i = 1; i <= n; i++){
		sum[i] = sum[i-1] + i*aux[i];
	}

	vector<ll> av(n+1, 0);
	for (int i = 1; i <= n; i++){
		av[i] = sum[i] + gr[i]*i;
	}

	auto bb = [&](int h){
		int ans = 0;
		int l = 0, r = n;
		while (l <= r){
			int w = (l+r)/2;
			int lim = min(h, w);
			if (ll(h)*ll(w) <= av[lim]){
				ans = max(ans, w);
				l = w+1;
			}
			else r = w-1;
		}
		return ans;
	};

	ll h = 1, w = 1;
	for (int i = 1; i <= n; i++){
		ll H = i, W = bb(i);
		if (W*H > w*h){
			w = W;
			h = H;
		}
	}
    swap(h, w);
	auto fix = [&](int I, int J){
		return make_pair(I%h, J%w);
	};
	vector<ii> order;
	for (int j = 0; j < w; j++){
		for (int i = 0; i < h; i++){
			order.push_back(fix(i, j+i));
		}
	}

	vector<vector<int>> p(h, vector<int>(w));
	vector<ii> repo;
	for (int i : el){
		int lim = min(freq[i], int(w));
		repo.push_back({lim, i});
	}
	sort(repo.begin(), repo.end(), greater<ii>());
	auto iter = repo.begin();
	auto next = [&](){
		if (iter->first == 0) iter++;
		iter->first--;
		return iter->second;
	};
	for (auto it : order){
		int i, j;
		tie(i, j) = it;
		p[i][j] = next();
	}
	cout << h*w << endl;
	cout << h << " " << w << endl;
	for (int i = 0; i < h; i++){
		for (int j = 0; j < w; j++)
			cout << back_cmp[p[i][j]] << " ";
		cout << endl;
	}

	exit(0);
}


#include <bits/stdc++.h>

using namespace std;

#define _ ios_base::sync_with_stdio(0);cin.tie(0);
#define endl '\n'

typedef long long ll;
typedef pair<int, int> ii;

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;

map<int, int> cmp;
map<int, int> back_cmp;

void compress(vector<int> &a){
	for (int &i : a){
		auto it = cmp.find(i);
		if (it != cmp.end()) continue;
		int sz = cmp.size();
		cmp[i] = sz;
		back_cmp[sz] = i;
	}
}

int main(){ _
	int n; cin >> n;;
	vector<int>	a(n);
	for (auto &it : a) cin >> it;
	compress(a);
	for (auto &it : a) it = cmp[it];

	set<int> el(a.begin(), a.end());

	vector<int> freq(n+1, 0);
	for (int i : a)
		freq[i]++;

	vector<int> aux(n+1, 0);
	for (auto i : el) aux[freq[i]]++;

	vector<int> gr(n+1, 0);
	for (int i = n-1; i >= 0; i--)
		gr[i] = gr[i+1] + aux[i+1];

	vector<ll> sum(n+1, 0);
	for (int i = 1; i <= n; i++){
		sum[i] = sum[i-1] + i*aux[i];
	}

	vector<ll> av(n+1, 0);
	for (int i = 1; i <= n; i++){
		av[i] = sum[i] + gr[i]*i;
	}

	auto bb = [&](int h){
		int ans = 0;
		int l = 0, r = n;
		while (l <= r){
			int w = (l+r)/2;
			int lim = min(h, w);
			if (ll(h)*ll(w) <= av[lim]){
				ans = max(ans, w);
				l = w+1;
			}
			else r = w-1;
		}
		return ans;
	};

	ll h = 1, w = 1;
	for (int i = 1; i <= n; i++){
		ll H = i, W = bb(i);
		if (W*H >= w*h){
			w = W;
			h = H;
		}
	}

	auto fix = [&](int I, int J){
		return make_pair(I%h, J%w);
	};
	vector<ii> order;
	for (int j = 0; j < w; j++){
		for (int i = 0; i < h; i++){
			order.push_back(fix(i, j+i));
		}
	}

	vector<vector<int>> p(h, vector<int>(w));
	vector<ii> repo;
	for (int i : el){
		int lim = min(freq[i], int(w));
		repo.push_back({lim, i});
	}
	sort(repo.begin(), repo.end(), greater<ii>());
	auto iter = repo.begin();
	auto next = [&](){
		if (iter->first == 0) iter++;
		iter->first--;
		return iter->second;
	};
	for (auto it : order){
		int i, j;
		tie(i, j) = it;
		p[i][j] = next();
	}
	cout << h*w << endl;
	cout << h << " " << w << endl;
	for (int i = 0; i < h; i++){
		for (int j = 0; j < w; j++)
			cout << back_cmp[p[i][j]] << " ";
		cout << endl;
	}

	exit(0);
}


#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <cassert>
#include <cstdio>
#include <algorithm>
#include <set>
#include <math.h>
#include <string>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <deque>
#include <iomanip>
#pragma GCC optimize(-Ofast)

#define pr pair
#define mp make_pair
#define ft first
#define sd second
#define ll long long
#define ld double
#define pii pr<int, int>
#define pll pr<ll, ll>

using namespace std;

int32_t main()
{
	cout.tie(NULL);
	cin.tie(NULL);
	int n;
	cin >> n;
	vector<int> a(n);
	for (int i = 0; i < n; i++)
		cin >> a[i];
	sort(a.begin(), a.end());
	vector<pii> newa(0);
	for (int i = 0; i < n; i++) {
		if (i > 0 && a[i] == a[i - 1])
			newa.back().first++;
		else
			newa.push_back(mp(1, a[i]));
	}
	sort(newa.begin(), newa.end());
	int newn = newa.size();
	vector<int> prefsum(newn + 1);
	prefsum[0] = 0;
	int ans = 0;
	int makeans = -1;
	int ansrows = -1;

	int lastrows = 0;
	for (int i = 1; i <= newn; i++) {

		for (int currows = lastrows + 1; currows <= newa[i - 1].ft; currows++) {
			int cols = prefsum[i - 1] / currows + (newn - i + 1);
			if (cols >= currows)
				if (ans < cols * currows) {
					ans = cols * currows;
					makeans = i - 1;
					ansrows = currows;
				}
			lastrows = currows;
		}
		prefsum[i] = prefsum[i - 1] + newa[i - 1].ft;
	}
	cout << ans << '\n' << '\n';
	int rows = ansrows;
	int cols = ans / rows;
	cout << rows << ' ' << cols << '\n' << '\n';
	vector<vector<int>> Ans(rows, vector<int>(cols, -1));
	int i = 0, j = 0;
	while (ans > 0) {
		for (int u = 0; u < makeans && ans > 0; u++) {
			while (newa[u].ft > 0 && ans > 0) {
				Ans[i][j] = newa[u].sd;
				newa[u].ft--;
				ans--;
				i++;
				j++;
				if (i >= rows)
					i -= rows;
				if (j >= cols)
					j -= cols;
				if (Ans[i][j] != -1)
					i++;
				if (i >= rows)
					i -= rows;
			}
		}
		for (int u = makeans; u < newn && ans > 0; u++) {
			for (int k = 0; k < rows && ans > 0; k++) {
				Ans[i][j] = newa[u].sd;
				newa[u].ft--;
				ans--;
				i++;
				j++;
				if (i >= rows)
					i -= rows;
				if (j >= cols)
					j -= cols;
				if (Ans[i][j] != -1)
					i++;
				if (i >= rows)
					i -= rows;
			}
		}
	}
	for (int i = 0; i < rows; i++) {
		for (int j = 0; j < cols; j++)
			cout << Ans[i][j] << ' ';
		cout << '\n';
	}
	int zero = 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <cassert>
#include <cstdio>
#include <algorithm>
#include <set>
#include <math.h>
#include <string>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <deque>
#include <iomanip>
#pragma GCC optimize(-Ofast)

#define pr pair
#define mp make_pair
#define ft first
#define sd second
#define ll long long
#define ld double
#define pii pr<int, int>
#define pll pr<ll, ll>

using namespace std;

int32_t main()
{
	cout.tie(NULL);
	cin.tie(NULL);
	int n;
	cin >> n;
	vector<int> a(n);
	for (int i = 0; i < n; i++)
		cin >> a[i];
	sort(a.begin(), a.end());
	vector<pii> newa(0);
	for (int i = 0; i < n; i++) {
		if (i > 0 && a[i] == a[i - 1])
			newa.back().first++;
		else
			newa.push_back(mp(1, a[i]));
	}
	sort(newa.begin(), newa.end());
	int newn = newa.size();
	vector<int> prefsum(newn + 1);
	prefsum[0] = 0;
	int ans = 0;
	int makeans = -1;
	int ansrows = -1;

	int lastrows = 0;
	for (int i = 1; i <= newn; i++) {

		for (int currows = lastrows + 1; currows <= newa[i - 1].ft; currows++) {
			int cols = prefsum[i - 1] / currows + (newn - i + 1);
			if (cols >= currows)
				if (ans < cols * currows) {
					ans = cols * currows;
					makeans = i - 1;
					ansrows = currows;
				}
			lastrows = currows;
		}
		prefsum[i] = prefsum[i - 1] + newa[i - 1].ft;
	}
	for (int currows = lastrows + 1; currows <= n; currows++) {
		int cols = prefsum[newn] / currows;
		if (cols >= currows)
			if (ans < cols * currows) {
				ans = cols * currows;
				makeans = newn;
				ansrows = currows;
			}
		lastrows = currows;
	}
	cout << ans << '\n' << '\n';
	int rows = ansrows;
	int cols = ans / rows;
	cout << rows << ' ' << cols << '\n' << '\n';
	vector<vector<int>> Ans(rows, vector<int>(cols, -1));
	int i = 0, j = 0;
	int minians = (cols - (newn - makeans)) * rows;
	while (ans > 0) {
		for (int u = 0; u < makeans && minians > 0; u++) {
			while (newa[u].ft > 0 && minians > 0) {
				Ans[i][j] = newa[u].sd;
				newa[u].ft--;
				ans--;
				minians--;
				i++;
				j++;
				if (i >= rows)
					i -= rows;
				if (j >= cols)
					j -= cols;
				if (Ans[i][j] != -1)
					j++;
				if (j >= cols)
					j -= cols;
			}
		}
		for (int u = makeans; u < newn && ans > 0; u++) {
			for (int k = 0; k < rows && ans > 0; k++) {
				Ans[i][j] = newa[u].sd;
				newa[u].ft--;
				ans--;
				i++;
				j++;
				if (i >= rows)
					i -= rows;
				if (j >= cols)
					j -= cols;
				if (Ans[i][j] != -1)
					j++;
				if (j >= cols)
					j -= cols;
			}
		}
	}
	for (int i = 0; i < rows; i++) {
		for (int j = 0; j < cols; j++)
			cout << Ans[i][j] << ' ';
		cout << '\n';
	}
	int zero = 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <cassert>
#include <cstdio>
#include <algorithm>
#include <set>
#include <math.h>
#include <string>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <deque>
#include <iomanip>
#pragma GCC optimize(-Ofast)

#define pr pair
#define mp make_pair
#define ft first
#define sd second
#define ll long long
#define ld double
#define pii pr<int, int>
#define pll pr<ll, ll>

using namespace std;

int32_t main()
{
	cout.tie(NULL);
	cin.tie(NULL);
	int n;
	cin >> n;
	vector<int> a(n);
	for (int i = 0; i < n; i++)
		cin >> a[i];
	sort(a.begin(), a.end());
	vector<pii> newa(0);
	for (int i = 0; i < n; i++) {
		if (i > 0 && a[i] == a[i - 1])
			newa.back().first++;
		else
			newa.push_back(mp(1, a[i]));
	}
	sort(newa.begin(), newa.end());
	int newn = newa.size();
	vector<int> prefsum(newn + 1);
	prefsum[0] = 0;
	int ans = 0;
	int makeans = -1;
	int ansrows = -1;

	int lastrows = 0;
	for (int i = 1; i <= newn; i++) {

		for (int currows = lastrows + 1; currows <= newa[i - 1].ft; currows++) {
			int cols = prefsum[i - 1] / currows + (newn - i + 1);
			if (cols >= currows)
				if (ans < cols * currows) {
					ans = cols * currows;
					makeans = i - 1;
					ansrows = currows;
				}
			lastrows = currows;
		}
		prefsum[i] = prefsum[i - 1] + newa[i - 1].ft;
	}
	cout << ans << '\n' << '\n';
	int rows = ansrows;
	int cols = ans / rows;
	cout << rows << ' ' << cols << '\n' << '\n';
	vector<vector<int>> Ans(rows, vector<int>(cols, -1));
	int i = 0, j = 0;
	int minians = (cols - (newn - makeans)) * rows;
	while (ans > 0) {
		for (int u = 0; u < makeans && minians > 0; u++) {
			while (newa[u].ft > 0 && minians > 0) {
				Ans[i][j] = newa[u].sd;
				newa[u].ft--;
				ans--;
				minians--;
				i++;
				j++;
				if (i >= rows)
					i -= rows;
				if (j >= cols)
					j -= cols;
				if (Ans[i][j] != -1)
					i++;
				if (i >= rows)
					i -= rows;
			}
		}
		for (int u = makeans; u < newn && ans > 0; u++) {
			for (int k = 0; k < rows && ans > 0; k++) {
				Ans[i][j] = newa[u].sd;
				newa[u].ft--;
				ans--;
				i++;
				j++;
				if (i >= rows)
					i -= rows;
				if (j >= cols)
					j -= cols;
				if (Ans[i][j] != -1)
					i++;
				if (i >= rows)
					i -= rows;
			}
		}
	}
	for (int i = 0; i < rows; i++) {
		for (int j = 0; j < cols; j++)
			cout << Ans[i][j] << ' ';
		cout << '\n';
	}
	int zero = 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <cassert>
#include <cstdio>
#include <algorithm>
#include <set>
#include <math.h>
#include <string>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <deque>
#include <iomanip>
#pragma GCC optimize(-Ofast)

#define pr pair
#define mp make_pair
#define ft first
#define sd second
#define ll long long
#define ld double
#define pii pr<int, int>
#define pll pr<ll, ll>

using namespace std;

int32_t main()
{
	cout.tie(NULL);
	cin.tie(NULL);
	int n;
	cin >> n;
	vector<int> a(n);
	for (int i = 0; i < n; i++)
		cin >> a[i];
	sort(a.begin(), a.end());
	vector<pii> newa(0);
	for (int i = 0; i < n; i++) {
		if (i > 0 && a[i] == a[i - 1])
			newa.back().first++;
		else
			newa.push_back(mp(1, a[i]));
	}
	sort(newa.begin(), newa.end());
	int newn = newa.size();
	vector<int> prefsum(newn + 1);
	prefsum[0] = 0;
	int ans = 0;
	int makeans = -1;
	int ansrows = -1;

	int lastrows = 0;
	for (int i = 1; i <= newn; i++) {

		for (int currows = lastrows + 1; currows <= newa[i - 1].ft; currows++) {
			int cols = prefsum[i - 1] / currows + (newn - i + 1);
			if (cols >= currows)
				if (ans < cols * currows) {
					ans = cols * currows;
					makeans = i - 1;
					ansrows = currows;
				}
			lastrows = currows;
		}
		prefsum[i] = prefsum[i - 1] + newa[i - 1].ft;
	}
	cout << ans << '\n';
	int rows = ansrows;
	int cols = ans / rows;
	cout << rows << ' ' << cols << '\n';
	vector<vector<int>> Ans(rows, vector<int>(cols, -1));
	int i = 0, j = 0;
	while (ans > 0) {
		for (int u = 0; u <= makeans && ans > 0; u++) {
			while (newa[u].ft > 0 && ans > 0) {
				Ans[i][j] = newa[u].sd;
				newa[u].ft--;
				ans--;
				i++;
				j++;
				if (i >= rows)
					i -= rows;
				if (j >= cols)
					j -= cols;
				if (Ans[i][j] != -1)
					i++;
				if (i >= rows)
					i -= rows;
			}
		}
		for (int u = makeans + 1; u < newn && ans > 0; u++) {
			for (int k = 0; k < rows && ans > 0; k++) {
				Ans[i][j] = newa[u].sd;
				newa[u].ft--;
				ans--;
				i++;
				j++;
				if (i >= rows)
					i -= rows;
				if (j >= cols)
					j -= cols;
				if (Ans[i][j] != -1)
					i++;
				if (i >= rows)
					i -= rows;
			}
		}
	}
	for (int i = 0; i < rows; i++) {
		for (int j = 0; j < cols; j++)
			cout << Ans[i][j] << ' ';
		cout << '\n';
	}
	int zero = 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <cassert>
#include <cstdio>
#include <algorithm>
#include <set>
#include <math.h>
#include <string>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <deque>
#include <iomanip>
#pragma GCC optimize(-Ofast)

#define pr pair
#define mp make_pair
#define ft first
#define sd second
#define ll long long
#define ld double
#define pii pr<int, int>
#define pll pr<ll, ll>

using namespace std;

int32_t main()
{
	cout.tie(NULL);
	cin.tie(NULL);
	int n;
	cin >> n;
	vector<int> a(n);
	for (int i = 0; i < n; i++)
		cin >> a[i];
	sort(a.begin(), a.end());
	vector<pii> newa(0);
	for (int i = 0; i < n; i++) {
		if (i > 0 && a[i] == a[i - 1])
			newa.back().first++;
		else
			newa.push_back(mp(1, a[i]));
	}
	sort(newa.begin(), newa.end());
	int newn = newa.size();
	vector<int> prefsum(newn + 1);
	prefsum[0] = 0;
	int ans = 0;
	int makeans = -1;
	int ansrows = -1;

	int lastrows = 0;
	for (int i = 1; i <= newn; i++) {

		for (int currows = lastrows + 1; currows <= newa[i - 1].ft; currows++) {
			int cols = prefsum[i - 1] / currows + (newn - i + 1);
			if (cols >= currows)
				if (ans < cols * currows) {
					ans = cols * currows;
					makeans = i - 1;
					ansrows = currows;
				}
			lastrows = currows;
		}
		prefsum[i] = prefsum[i - 1] + newa[i - 1].ft;
	}
	for (int currows = lastrows + 1; currows <= n; currows++) {
		int cols = prefsum[newn] / currows;
		if (cols >= currows)
			if (ans < cols * currows) {
				ans = cols * currows;
				makeans = newn;
				ansrows = currows;
			}
		lastrows = currows;
	}
	cout << ans << '\n' << '\n';
	int rows = ansrows;
	int cols = ans / rows;
	cout << rows << ' ' << cols << '\n' << '\n';
	vector<vector<int>> Ans(rows, vector<int>(cols, -1));
	int i = 0, j = 0;
	int minians = (cols - (newn - makeans)) * rows;
	while (ans > 0) {
		for (int u = 0; u < makeans && minians > 0; u++) {
			while (newa[u].ft > 0 && minians > 0) {
				Ans[i][j] = newa[u].sd;
				newa[u].ft--;
				ans--;
				minians--;
				i++;
				j++;
				if (i >= rows)
					i -= rows;
				if (j >= cols)
					j -= cols;
				if (Ans[i][j] != -1)
					j++;
				if (j >= cols)
					j -= cols;
			}
		}
		for (int u = makeans; u < newn && ans > 0; u++) {
			for (int k = 0; k < rows && ans > 0; k++) {
				Ans[i][j] = newa[u].sd;
				newa[u].ft--;
				ans--;
				i++;
				j++;
				if (i >= rows)
					i -= rows;
				if (j >= cols)
					j -= cols;
				if (Ans[i][j] != -1)
					i++;
				if (i >= rows)
					i -= rows;
			}
		}
	}
	for (int i = 0; i < rows; i++) {
		for (int j = 0; j < cols; j++)
			cout << Ans[i][j] << ' ';
		cout << '\n';
	}
	int zero = 0;
}


#include <bits/stdc++.h>

using namespace std;

typedef unsigned long long ull;
typedef long long ll;
typedef long double ld;

#define int ll
#define rand shittttty_shit
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
mt19937_64 rng_64(chrono::steady_clock::now().time_since_epoch().count());

typedef pair<int, int> pii;
typedef pair<string, string> pst;
typedef pair<pii, pii> piii;
typedef vector<piii> vpii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
typedef vector< vi > vvi;
typedef vector< vvi > vvvi;
typedef vector<pii> vpi;
typedef vector<short> vs;
typedef vector<vs> vvs;
typedef vector<vvs> vvvs;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<vvl> vvvl;
typedef vector<ld> vld;
typedef vector<vld> vvld;
typedef vector<vvld> vvvld;
typedef vector<string> vst;
typedef vector<vst> vvst;
typedef pair<ld, ld> pld;
typedef pair<pld, pld> pldd;
typedef vector<pld> vpd;
typedef complex<double> base;

#define inmin(a, b) a = min(a, (b))
#define inmax(a, b) a = max(a, (b))
#define my_abs(a) (((a) >= 0) ? (a) : -(a))
#define mp(a, b) make_pair(a, (b))
#define ALL(a) a.begin(),a.end()
#define RALL(a) a.rbegin(),a.rend()
#define sqr(x) ((x) * (x))
#define fori(i, n) for(int i = 0; i < int(n); ++i)
#define SZ(a) ((int)((a).size()))
#define MODIK(a) (a >= M ? a - M : a)
#define triple(T) tuple<T, T, T>
#define quad(T) tuple<T, T, T, T>
#define watch(x) cout << (#x) << " = " << x << endl;
#ifdef MAX_HOME
#define cerr cout
#else
#define cerr if (false) cerr
#endif

const double PI = 2 * acos(0.0);

const string DIGITS = "0123456789";
const string ALPH = "abcdefghijklmnopqrstuvwxyz";

istream &operator >> (istream &in, pii &a)
{
    in >> a.first >> a.second;
    return in;
}

ostream &operator << (ostream &out, pii &a)
{
    out << a.first << ' ' << a.second;
    return out;
}

istream &operator >> (istream &in, pld &a)
{
    in >> a.first >> a.second;
    return in;
}

ostream &operator << (ostream &out, pld &a)
{
    out << a.first << ' ' << a.second;
    return out;
}

template <class T0, class T1>
inline ostream & operator << (ostream &out, pair<T0, T1> &a) {
    return out << "{" << a.first << ", " << a.second << "}";
}

template <class T0, class T1, class T2>
inline ostream & operator << (ostream &out, tuple<T0, T1, T2> &a) {
    return out << "{" << get<0>(a) << ", " << get<1>(a) << ", " << get<2>(a) << "}";
}

template <class T0, class T1, class T2, class T3>
inline ostream & operator << (ostream &out, tuple<T0, T1, T2, T3> &a) {
    return out << "{" << get<0>(a) << ", " << get<1>(a) <<
               ", " << get<2>(a) << ", " <<  get<3>(a) << "}";
}

template<class T>
inline ostream & operator << (ostream &out, vector<T> &a) {
    out << "[";
    fori (i, a.size())
        out << a[i] << vector<string>{", ", "]  "}[i + 1 == a.size()];
    return out;
}

void print(vi kek, int k)
{
    ofstream cout("output.txt");
    cout << SZ(kek) << ' ' << k << '\n';
    for (auto p : kek) {
        cout << p << ' ';
    }
    cout.close();
    exit(0);
}

inline bool break_time(ld time)
{
    return clock() > CLOCKS_PER_SEC * time;
}

ld get_rand_ld(ld l, ld r)
{
    uniform_real_distribution<double> gen(l, r);
    return gen(rng);
}

void smain();

signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);

#ifdef ART_HOME
    freopen("input.txt", "r", stdin);
    clock_t start = clock();
#endif
    cout << setprecision(12) << fixed;
    smain();
#ifdef ART_HOME
    cout << "\n\n\nTOTAL EXECUTION TIME: " << float( clock () - start ) /  CLOCKS_PER_SEC << endl;
#endif
}

const int M1 = 1000000093, p1 = 27162;
const int M2 = 1000000087, p2 = 241;

const int N = 5e3 + 10, B = 330, oo = 1e9, A = 26, M = 1e9 + 7;

int dp[N][N];

void smain() {
    int n;
    cin >> n;

    map<int, int> d;

    for (int i = 0; i < n; ++i) {
        int a;
        cin >> a;
        d[a]++;
    }

    vpi kek;
    for (pii p : d)
        kek.push_back(mp(p.second, p.first));

    stable_sort(ALL(kek));
    vi pref(SZ(kek));

    for (int i = 0; i < SZ(kek); ++i)
        pref[i] = kek[i].first;

    for (int i = 1; i < SZ(kek); ++i)
        pref[i] += pref[i - 1];

    pii ans = mp(0, 0);

    for (int i = 1; i <= n; ++i) {
        int l = -1, r = SZ(kek);
        while (r - l > 1) {
            int m = (l + r) >> 1;
            if (kek[m].first > i)
                r = m;
            else
                l = m;
        }

        int d = 0;
        if (l != -1)
            d += pref[l];

        d += (SZ(kek) - r) * i;
        d -= d % i;

        if (d > ans.first && d / i >= i)
            ans = mp(d, i);
    }

    cout << ans.first << '\n';
    cout << ans.first / ans.second << ' ' << ans.second << '\n';

    for (auto &p : kek)
        p.first = min(p.first, ans.second);

    vi lel;
    for (auto p : kek)
        for (int i = 0; i < p.first; ++i)
            lel.push_back(p.second);

    for (int i = 0; i < ans.first / ans.second; ++i) {
        int st = i;

        for (int j = 0; j < ans.second; ++j) {
            dp[st][j] = lel.back();
            lel.pop_back();
            st++;

            if (st >= ans.first / ans.second)
                st = 0;
        }
    }

    for (int i = 0; i < ans.first / ans.second; ++i)
    {
        for (int j = 0; j < ans.second; ++j)
            cout << dp[i][j] << ' ';

        cout << '\n';
    }
}


#include <bits/stdc++.h>

using namespace std;

typedef unsigned long long ull;
typedef long long ll;
typedef long double ld;

#define int ll
#define rand shittttty_shit
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
mt19937_64 rng_64(chrono::steady_clock::now().time_since_epoch().count());

typedef pair<int, int> pii;
typedef pair<string, string> pst;
typedef pair<pii, pii> piii;
typedef vector<piii> vpii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
typedef vector< vi > vvi;
typedef vector< vvi > vvvi;
typedef vector<pii> vpi;
typedef vector<short> vs;
typedef vector<vs> vvs;
typedef vector<vvs> vvvs;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<vvl> vvvl;
typedef vector<ld> vld;
typedef vector<vld> vvld;
typedef vector<vvld> vvvld;
typedef vector<string> vst;
typedef vector<vst> vvst;
typedef pair<ld, ld> pld;
typedef pair<pld, pld> pldd;
typedef vector<pld> vpd;
typedef complex<double> base;

#define inmin(a, b) a = min(a, (b))
#define inmax(a, b) a = max(a, (b))
#define my_abs(a) (((a) >= 0) ? (a) : -(a))
#define mp(a, b) make_pair(a, (b))
#define ALL(a) a.begin(),a.end()
#define RALL(a) a.rbegin(),a.rend()
#define sqr(x) ((x) * (x))
#define fori(i, n) for(int i = 0; i < int(n); ++i)
#define SZ(a) ((int)((a).size()))
#define MODIK(a) (a >= M ? a - M : a)
#define triple(T) tuple<T, T, T>
#define quad(T) tuple<T, T, T, T>
#define watch(x) cout << (#x) << " = " << x << endl;
#ifdef MAX_HOME
#define cerr cout
#else
#define cerr if (false) cerr
#endif

const double PI = 2 * acos(0.0);

const string DIGITS = "0123456789";
const string ALPH = "abcdefghijklmnopqrstuvwxyz";

istream &operator >> (istream &in, pii &a)
{
    in >> a.first >> a.second;
    return in;
}

ostream &operator << (ostream &out, pii &a)
{
    out << a.first << ' ' << a.second;
    return out;
}

istream &operator >> (istream &in, pld &a)
{
    in >> a.first >> a.second;
    return in;
}

ostream &operator << (ostream &out, pld &a)
{
    out << a.first << ' ' << a.second;
    return out;
}

template <class T0, class T1>
inline ostream & operator << (ostream &out, pair<T0, T1> &a) {
    return out << "{" << a.first << ", " << a.second << "}";
}

template <class T0, class T1, class T2>
inline ostream & operator << (ostream &out, tuple<T0, T1, T2> &a) {
    return out << "{" << get<0>(a) << ", " << get<1>(a) << ", " << get<2>(a) << "}";
}

template <class T0, class T1, class T2, class T3>
inline ostream & operator << (ostream &out, tuple<T0, T1, T2, T3> &a) {
    return out << "{" << get<0>(a) << ", " << get<1>(a) <<
               ", " << get<2>(a) << ", " <<  get<3>(a) << "}";
}

template<class T>
inline ostream & operator << (ostream &out, vector<T> &a) {
    out << "[";
    fori (i, a.size())
        out << a[i] << vector<string>{", ", "]  "}[i + 1 == a.size()];
    return out;
}

void print(vi kek, int k)
{
    ofstream cout("output.txt");
    cout << SZ(kek) << ' ' << k << '\n';
    for (auto p : kek) {
        cout << p << ' ';
    }
    cout.close();
    exit(0);
}

inline bool break_time(ld time)
{
    return clock() > CLOCKS_PER_SEC * time;
}

ld get_rand_ld(ld l, ld r)
{
    uniform_real_distribution<double> gen(l, r);
    return gen(rng);
}

void smain();

signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);

#ifdef ART_HOME
    freopen("input.txt", "r", stdin);
    clock_t start = clock();
#endif
    cout << setprecision(12) << fixed;
    smain();
#ifdef ART_HOME
    cout << "\n\n\nTOTAL EXECUTION TIME: " << float( clock () - start ) /  CLOCKS_PER_SEC << endl;
#endif
}

const int M1 = 1000000093, p1 = 27162;
const int M2 = 1000000087, p2 = 241;

const int N = 1e4 + 10, B = 330, oo = 1e9, A = 26, M = 1e9 + 7;

signed dp[N][N];

void smain() {
    int n;
    cin >> n;

    map<int, int> d;

    for (int i = 0; i < n; ++i) {
        int a;
        cin >> a;
        d[a]++;
    }

    vpi kek;
    for (pii p : d)
        kek.push_back(mp(p.second, p.first));

    stable_sort(ALL(kek));
    vi pref(SZ(kek));

    for (int i = 0; i < SZ(kek); ++i)
        pref[i] = kek[i].first;

    for (int i = 1; i < SZ(kek); ++i)
        pref[i] += pref[i - 1];

    pii ans = mp(0, 0);

    for (int i = 1; i <= n; ++i) {
        int l = -1, r = SZ(kek);
        while (r - l > 1) {
            int m = (l + r) >> 1;
            if (kek[m].first > i)
                r = m;
            else
                l = m;
        }

        int d = 0;
        if (l != -1)
            d += pref[l];

        d += (SZ(kek) - r) * i;
        d -= d % i;

        if (d > ans.first && d / i >= i)
            ans = mp(d, i);
    }

    cout << ans.first << '\n';
    cout << ans.first / ans.second << ' ' << ans.second << '\n';

    for (auto &p : kek)
        p.first = min(p.first, ans.second);

    vi lel;
    for (auto p : kek)
        for (int i = 0; i < p.first; ++i)
            lel.push_back(p.second);

    for (int i = 0; i < ans.first / ans.second; ++i) {
        int st = i;

        for (int j = 0; j < ans.second; ++j) {
            dp[st][j] = lel.back();
            lel.pop_back();
            st++;

            if (st >= ans.first / ans.second)
                st = 0;
        }
    }

    for (int i = 0; i < ans.first / ans.second; ++i)
    {
        for (int j = 0; j < ans.second; ++j)
            cout << dp[i][j] << ' ';

        cout << '\n';
    }
}


#include <bits/stdc++.h>

using namespace std;

typedef unsigned long long ull;
typedef long long ll;
typedef long double ld;

#define int ll
#define rand shittttty_shit
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
mt19937_64 rng_64(chrono::steady_clock::now().time_since_epoch().count());

typedef pair<int, int> pii;
typedef pair<string, string> pst;
typedef pair<pii, pii> piii;
typedef vector<piii> vpii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
typedef vector< vi > vvi;
typedef vector< vvi > vvvi;
typedef vector<pii> vpi;
typedef vector<short> vs;
typedef vector<vs> vvs;
typedef vector<vvs> vvvs;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<vvl> vvvl;
typedef vector<ld> vld;
typedef vector<vld> vvld;
typedef vector<vvld> vvvld;
typedef vector<string> vst;
typedef vector<vst> vvst;
typedef pair<ld, ld> pld;
typedef pair<pld, pld> pldd;
typedef vector<pld> vpd;
typedef complex<double> base;

#define inmin(a, b) a = min(a, (b))
#define inmax(a, b) a = max(a, (b))
#define my_abs(a) (((a) >= 0) ? (a) : -(a))
#define mp(a, b) make_pair(a, (b))
#define ALL(a) a.begin(),a.end()
#define RALL(a) a.rbegin(),a.rend()
#define sqr(x) ((x) * (x))
#define fori(i, n) for(int i = 0; i < int(n); ++i)
#define SZ(a) ((int)((a).size()))
#define MODIK(a) (a >= M ? a - M : a)
#define triple(T) tuple<T, T, T>
#define quad(T) tuple<T, T, T, T>
#define watch(x) cout << (#x) << " = " << x << endl;
#ifdef MAX_HOME
#define cerr cout
#else
#define cerr if (false) cerr
#endif

const double PI = 2 * acos(0.0);

const string DIGITS = "0123456789";
const string ALPH = "abcdefghijklmnopqrstuvwxyz";

istream &operator >> (istream &in, pii &a)
{
    in >> a.first >> a.second;
    return in;
}

ostream &operator << (ostream &out, pii &a)
{
    out << a.first << ' ' << a.second;
    return out;
}

istream &operator >> (istream &in, pld &a)
{
    in >> a.first >> a.second;
    return in;
}

ostream &operator << (ostream &out, pld &a)
{
    out << a.first << ' ' << a.second;
    return out;
}

template <class T0, class T1>
inline ostream & operator << (ostream &out, pair<T0, T1> &a) {
    return out << "{" << a.first << ", " << a.second << "}";
}

template <class T0, class T1, class T2>
inline ostream & operator << (ostream &out, tuple<T0, T1, T2> &a) {
    return out << "{" << get<0>(a) << ", " << get<1>(a) << ", " << get<2>(a) << "}";
}

template <class T0, class T1, class T2, class T3>
inline ostream & operator << (ostream &out, tuple<T0, T1, T2, T3> &a) {
    return out << "{" << get<0>(a) << ", " << get<1>(a) <<
               ", " << get<2>(a) << ", " <<  get<3>(a) << "}";
}

template<class T>
inline ostream & operator << (ostream &out, vector<T> &a) {
    out << "[";
    fori (i, a.size())
        out << a[i] << vector<string>{", ", "]  "}[i + 1 == a.size()];
    return out;
}

void print(vi kek, int k)
{
    ofstream cout("output.txt");
    cout << SZ(kek) << ' ' << k << '\n';
    for (auto p : kek) {
        cout << p << ' ';
    }
    cout.close();
    exit(0);
}

inline bool break_time(ld time)
{
    return clock() > CLOCKS_PER_SEC * time;
}

ld get_rand_ld(ld l, ld r)
{
    uniform_real_distribution<double> gen(l, r);
    return gen(rng);
}

void smain();

signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);

#ifdef ART_HOME
    freopen("input.txt", "r", stdin);
    clock_t start = clock();
#endif
    cout << setprecision(12) << fixed;
    smain();
#ifdef ART_HOME
    cout << "\n\n\nTOTAL EXECUTION TIME: " << float( clock () - start ) /  CLOCKS_PER_SEC << endl;
#endif
}

const int M1 = 1000000093, p1 = 27162;
const int M2 = 1000000087, p2 = 241;

const int N = 6e3 + 10, B = 330, oo = 1e9, A = 26, M = 1e9 + 7;

void smain() {
    int n;
    cin >> n;

    map<int, int> d;

    for (int i = 0; i < n; ++i) {
        int a;
        cin >> a;
        d[a]++;
    }

    vpi kek;
    for (pii p : d)
        kek.push_back(mp(p.second, p.first));

    stable_sort(ALL(kek));
    vi pref(SZ(kek));

    for (int i = 0; i < SZ(kek); ++i)
        pref[i] = kek[i].first;

    for (int i = 1; i < SZ(kek); ++i)
        pref[i] += pref[i - 1];

    pii ans = mp(0, 0);

    for (int i = 1; i <= n; ++i) {
        int l = -1, r = SZ(kek);
        while (r - l > 1) {
            int m = (l + r) >> 1;
            if (kek[m].first > i)
                r = m;
            else
                l = m;
        }

        int d = 0;
        if (l != -1)
            d += pref[l];

        d += (SZ(kek) - r) * i;
        d -= d % i;

        if (d > ans.first && d / i >= i)
            ans = mp(d, i);
    }

    cout << ans.first << '\n';
    cout << ans.first / ans.second << ' ' << ans.second << '\n';

    for (auto &p : kek)
        p.first = min(p.first, ans.second);

    vi lel;
    for (auto p : kek)
        for (int i = 0; i < p.first; ++i)
            lel.push_back(p.second);

    vvi dp(ans.first / ans.second);
    for (int i = 0; i < SZ(dp); ++i)
        dp[i].resize(ans.second);

    for (int i = 0; i < ans.first / ans.second; ++i) {
        int st = i;

        for (int j = 0; j < ans.second; ++j) {
            dp[st][j] = lel.back();
            lel.pop_back();
            st++;

            if (st >= ans.first / ans.second)
                st = 0;
        }
    }

    for (int i = 0; i < ans.first / ans.second; ++i)
    {
        for (int j = 0; j < ans.second; ++j)
            cout << dp[i][j] << ' ';

        cout << '\n';
    }
}


#include <bits/stdc++.h>

using namespace std;

typedef unsigned long long ull;
typedef long long ll;
typedef long double ld;

#define int ll
#define rand shittttty_shit
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
mt19937_64 rng_64(chrono::steady_clock::now().time_since_epoch().count());

typedef pair<int, int> pii;
typedef pair<string, string> pst;
typedef pair<pii, pii> piii;
typedef vector<piii> vpii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
typedef vector< vi > vvi;
typedef vector< vvi > vvvi;
typedef vector<pii> vpi;
typedef vector<short> vs;
typedef vector<vs> vvs;
typedef vector<vvs> vvvs;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<vvl> vvvl;
typedef vector<ld> vld;
typedef vector<vld> vvld;
typedef vector<vvld> vvvld;
typedef vector<string> vst;
typedef vector<vst> vvst;
typedef pair<ld, ld> pld;
typedef pair<pld, pld> pldd;
typedef vector<pld> vpd;
typedef complex<double> base;

#define inmin(a, b) a = min(a, (b))
#define inmax(a, b) a = max(a, (b))
#define my_abs(a) (((a) >= 0) ? (a) : -(a))
#define mp(a, b) make_pair(a, (b))
#define ALL(a) a.begin(),a.end()
#define RALL(a) a.rbegin(),a.rend()
#define sqr(x) ((x) * (x))
#define fori(i, n) for(int i = 0; i < int(n); ++i)
#define SZ(a) ((int)((a).size()))
#define MODIK(a) (a >= M ? a - M : a)
#define triple(T) tuple<T, T, T>
#define quad(T) tuple<T, T, T, T>
#define watch(x) cout << (#x) << " = " << x << endl;
#ifdef MAX_HOME
#define cerr cout
#else
#define cerr if (false) cerr
#endif

const double PI = 2 * acos(0.0);

const string DIGITS = "0123456789";
const string ALPH = "abcdefghijklmnopqrstuvwxyz";

istream &operator >> (istream &in, pii &a)
{
    in >> a.first >> a.second;
    return in;
}

ostream &operator << (ostream &out, pii &a)
{
    out << a.first << ' ' << a.second;
    return out;
}

istream &operator >> (istream &in, pld &a)
{
    in >> a.first >> a.second;
    return in;
}

ostream &operator << (ostream &out, pld &a)
{
    out << a.first << ' ' << a.second;
    return out;
}

template <class T0, class T1>
inline ostream & operator << (ostream &out, pair<T0, T1> &a) {
    return out << "{" << a.first << ", " << a.second << "}";
}

template <class T0, class T1, class T2>
inline ostream & operator << (ostream &out, tuple<T0, T1, T2> &a) {
    return out << "{" << get<0>(a) << ", " << get<1>(a) << ", " << get<2>(a) << "}";
}

template <class T0, class T1, class T2, class T3>
inline ostream & operator << (ostream &out, tuple<T0, T1, T2, T3> &a) {
    return out << "{" << get<0>(a) << ", " << get<1>(a) <<
               ", " << get<2>(a) << ", " <<  get<3>(a) << "}";
}

template<class T>
inline ostream & operator << (ostream &out, vector<T> &a) {
    out << "[";
    fori (i, a.size())
        out << a[i] << vector<string>{", ", "]  "}[i + 1 == a.size()];
    return out;
}

void print(vi kek, int k)
{
    ofstream cout("output.txt");
    cout << SZ(kek) << ' ' << k << '\n';
    for (auto p : kek) {
        cout << p << ' ';
    }
    cout.close();
    exit(0);
}

inline bool break_time(ld time)
{
    return clock() > CLOCKS_PER_SEC * time;
}

ld get_rand_ld(ld l, ld r)
{
    uniform_real_distribution<double> gen(l, r);
    return gen(rng);
}

void smain();

signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);

#ifdef ART_HOME
    freopen("input.txt", "r", stdin);
    clock_t start = clock();
#endif
    cout << setprecision(12) << fixed;
    smain();
#ifdef ART_HOME
    cout << "\n\n\nTOTAL EXECUTION TIME: " << float( clock () - start ) /  CLOCKS_PER_SEC << endl;
#endif
}

const int M1 = 1000000093, p1 = 27162;
const int M2 = 1000000087, p2 = 241;

const int N = 8e3 + 10, B = 330, oo = 1e9, A = 26, M = 1e9 + 7;

signed dp[N][N];

void smain() {
    int n;
    cin >> n;

    map<int, int> d;

    for (int i = 0; i < n; ++i) {
        int a;
        cin >> a;
        d[a]++;
    }

    vpi kek;
    for (pii p : d)
        kek.push_back(mp(p.second, p.first));

    stable_sort(ALL(kek));
    vi pref(SZ(kek));

    for (int i = 0; i < SZ(kek); ++i)
        pref[i] = kek[i].first;

    for (int i = 1; i < SZ(kek); ++i)
        pref[i] += pref[i - 1];

    pii ans = mp(0, 0);

    for (int i = 1; i <= n; ++i) {
        int l = -1, r = SZ(kek);
        while (r - l > 1) {
            int m = (l + r) >> 1;
            if (kek[m].first > i)
                r = m;
            else
                l = m;
        }

        int d = 0;
        if (l != -1)
            d += pref[l];

        d += (SZ(kek) - r) * i;
        d -= d % i;

        if (d > ans.first && d / i >= i)
            ans = mp(d, i);
    }

    cout << ans.first << '\n';
    cout << ans.first / ans.second << ' ' << ans.second << '\n';

    for (auto &p : kek)
        p.first = min(p.first, ans.second);

    vi lel;
    for (auto p : kek)
        for (int i = 0; i < p.first; ++i)
            lel.push_back(p.second);

    for (int i = 0; i < ans.first / ans.second; ++i) {
        int st = i;

        for (int j = 0; j < ans.second; ++j) {
            dp[st][j] = lel.back();
            lel.pop_back();
            st++;

            if (st >= ans.first / ans.second)
                st = 0;
        }
    }

    for (int i = 0; i < ans.first / ans.second; ++i)
    {
        for (int j = 0; j < ans.second; ++j)
            cout << dp[i][j] << ' ';

        cout << '\n';
    }
}


/*input
9
1 2 3 1 2 3 1 1 2
*/
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define pb push_back
#define x first
#define y second
#define all(a) a.begin(), a.end()
#define sz(a) (int)a.size()
#define rd() abs((int)rng())
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
const int maxn = 4e5 + 100;
const int mod = 1e9 + 7;
mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());
set<pii>se;
void construct(int h, int w)
{
	cout << h * w << "\n";
	cout << h << " " << w << "\n";
	int cur = 0;
	vector<vector<int> >ans(h + 2, vector<int>(w + 2, 0));
	for(pii p : se)
	{
		int cnt = min(-p.x, h);
		while(cnt > 0)
		{
			int col = cur % w;
			int row = (cur / w + cur % w) % h;
			ans[row][col] = p.y;
			cur++;
			cnt--;
		}
	}
	for(int i = 0; i < h; i++)
	{
		set<int>st;
		for(int j = 0; j < w; j++)
		{
			if(st.count(ans[i][j]))
				assert(false);
			st.insert(ans[i][j]);
		}
	}
	for(int j = 0; j < w; j++)
	{
		set<int>st;
		for(int i = 0; i < h; i++)
		{
			if(st.count(ans[i][j]))
				assert(false);
			st.insert(ans[i][j]);
		}
	}
	for(int i = 0; i < h; i++)
	{
		for(int j = 0; j < w; j++)
			cout << ans[i][j] << " ";
		cout << "\n";
	}
}
int main()
{
	ios_base::sync_with_stdio(false), cin.tie(0);
	int n;
	cin >> n;
	vector<int>v(n + 1, 0);
	map<int, int>mp;
	for(int i = 1; i <= n; i++)
	{
		cin >> v[i];
		mp[v[i]]++;
	}

	vector<int>vec;
	for(auto aa : mp)
	{
		se.insert({-aa.y, aa.x});
		for(int i = 1; i <= aa.y; i++)
			vec.pb(i);
	}

	sort(all(vec));

	int besth = 0, bestw = 0;
	for(int h = 1; h * h <= n; h++)
	{
		int w = (upper_bound(all(vec), h) - vec.begin()) / h;
		if(w >= h)
		{
			if(h * w >= besth * bestw)
				besth = h, bestw = w;
		}
	}

	construct(besth, bestw);
	return 0;
}


/*input
20
1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 5 6 7 8
*/
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define pb push_back
#define x first
#define y second
#define all(a) a.begin(), a.end()
#define sz(a) (int)a.size()
#define rd() abs((int)rng())
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
const int maxn = 4e5 + 100;
const int mod = 1e9 + 7;
mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());
set<pii>se;
void construct(int h, int w)
{
	cout << h * w << "\n";
	cout << h << " " << w << "\n";
	int cur = 0;
	vector<vector<int> >ans(h + 5, vector<int>(w + 5, 0));
	int now = 0;
	for(pii p : se)
	{
		int cnt = min(-p.x, h);
		while(cnt > 0)
		{
			int col = cur % w;
			if(col == 0)
				now = cur / w;
			int row = now % h;
			ans[row][col] = p.y;
			cur++;
			cnt--;
			now++;
		}
	}
	for(int i = 0; i < h; i++)
	{
		for(int j = 0; j < w; j++)
			cout << ans[i][j] << " ";
		cout << "\n";
	}
}
int main()
{
	ios_base::sync_with_stdio(false), cin.tie(0);
	int n;
	cin >> n;
	vector<int>v(n + 1, 0);
	map<int, int>mp;
	for(int i = 1; i <= n; i++)
	{
		cin >> v[i];
		mp[v[i]]++;
	}

	int mx = 0;
	int cur = 1;
	vector<int>vec;
	for(auto aa : mp)
	{
		se.insert({-aa.y, aa.x});
		for(int i = 1; i <= aa.y; i++)
			vec.pb(i);
		mx = max(mx, aa.y);
		cur++;
	}

	sort(all(v));
	int besth = 0, bestw = 0;
	for(int h = 1; h <= mx; h++)
	{
		int w = (upper_bound(all(vec), h) - vec.begin()) / h;
		if(w >= h)
		{
			if(h * w >= besth * bestw)
				besth = h, bestw = w;
		}
	}

	construct(besth, bestw);
	return 0;
}


/*input
5
1 1 1 1 1
*/
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define pb push_back
#define x first
#define y second
#define all(a) a.begin(), a.end()
#define sz(a) (int)a.size()
#define rd() abs((int)rng())
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
const int maxn = 4e5 + 100;
const int mod = 1e9 + 7;
mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());
template<class T> using ordered_set = tree<T, null_type, greater_equal<T>, rb_tree_tag, tree_order_statistics_node_update>;
set<pii>se;
bool can(int h)
{
	int tot = 0;
	for(pii p : se)
		tot += min(-p.x, h);
	int w = 1;
	while(h * (w + 1) <= tot)
		w++;
	if(w < h)
		return false;
	return true;
}
void construct(int h)
{
	int w = h;
	int tot = 0;
	for(pii p : se)
		tot += min(-p.x, h);
	while(h * (w + 1) <= tot)
		w++;
	cout << h * w << "\n";
	cout << h << " " << w << "\n";
	int cur = 0;
	vector<vector<int> >ans(h + 5, vector<int>(w + 5, 0));
	for(pii p : se)
	{
		int cnt = min(-p.x, h);
		while(cnt > 0)
		{
			int col = cur % w;
			int row = (cur % w + cur / w) % h;
			ans[row][col] = p.y;
			cur++;
			cnt--;
		}
	}
	for(int i = 0; i < h; i++)
	{
		for(int j = 0; j < w; j++)
			cout << ans[i][j] << " ";
		cout << "\n";
	}
}
int main()
{
	ios_base::sync_with_stdio(false), cin.tie(0);
	int n;
	cin >> n;
	vector<int>v(n + 1, 0);
	map<int, int>mp;
	for(int i = 1; i <= n; i++)
	{
		cin >> v[i];
		mp[v[i]]++;
	}

	int mx = 0;
	for(auto aa : mp)
	{
		mx = max(mx, aa.y);
		se.insert({-aa.y, aa.x});
	}

	int lo = 1, hi = mx;
	while(lo < hi)
	{
		int mid = (lo + hi + 1) / 2;
		if(can(mid))
			lo = mid;
		else
			hi = mid - 1;
	}
	construct(lo);
	return 0;
}


/*input
20
1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 5 6 7 8
*/
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define pb push_back
#define x first
#define y second
#define all(a) a.begin(), a.end()
#define sz(a) (int)a.size()
#define rd() abs((int)rng())
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
const int maxn = 4e5 + 100;
const int mod = 1e9 + 7;
mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());
template<class T> using ordered_set = tree<T, null_type, less_equal<T>, rb_tree_tag, tree_order_statistics_node_update>;
set<pii>se;
void construct(int h, int w)
{
	cout << h * w << "\n";
	cout << h << " " << w << "\n";
	int cur = 0;
	vector<vector<int> >ans(h + 5, vector<int>(w + 5, 0));
	int now = 0;
	for(pii p : se)
	{
		int cnt = min(-p.x, h);
		while(cnt > 0)
		{
			int col = cur % w;
			if(col == 0)
				now = cur / w;
			int row = now % h;
			ans[row][col] = p.y;
			cur++;
			cnt--;
			now++;
		}
	}
	for(int i = 0; i < h; i++)
	{
		for(int j = 0; j < w; j++)
			cout << ans[i][j] << " ";
		cout << "\n";
	}
}
int main()
{
	ios_base::sync_with_stdio(false), cin.tie(0);
	int n;
	cin >> n;
	vector<int>v(n + 1, 0);
	map<int, int>mp;
	for(int i = 1; i <= n; i++)
	{
		cin >> v[i];
		mp[v[i]]++;
	}

	int mx = 0;
	int cur = 1;
	ordered_set<int>os;
	for(auto aa : mp)
	{
		se.insert({-aa.y, aa.x});
		for(int i = 1; i <= aa.y; i++)
			os.insert(i);
		mx = max(mx, aa.y);
		cur++;
	}

	int besth = 0, bestw = 0;
	for(int i = 1; i <= mx; i++)
	{
		int l = 1, r = n / i;
		while(l < r)
		{
			int mid = (l + r + 1) / 2;
			if(os.order_of_key(mid) >= 1ll * mid * i)
				l = mid;
			else
				r = mid - 1;
		}
		if(l >= i)
		{
			if(i * l >= besth * bestw)
				besth = i, bestw = l;
		}
	}

	construct(besth, bestw);
	return 0;
}


/*input
20
1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 5 6 7 8
*/
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define pb push_back
#define x first
#define y second
#define all(a) a.begin(), a.end()
#define sz(a) (int)a.size()
#define rd() abs((int)rng())
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
const int maxn = 4e5 + 100;
const int mod = 1e9 + 7;
mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());
set<pii>se;
void construct(int h, int w)
{
	cout << h * w << "\n";
	cout << h << " " << w << "\n";
	int cur = 0;
	vector<vector<int> >ans(h + 5, vector<int>(w + 5, 0));
	int now = 0;
	for(pii p : se)
	{
		int cnt = min(-p.x, h);
		while(cnt > 0)
		{
			int col = cur % w;
			if(col == 0)
				now = cur / w;
			int row = now % h;
			ans[row][col] = p.y;
			cur++;
			cnt--;
			now++;
		}
	}
	for(int i = 0; i < h; i++)
	{
		for(int j = 0; j < w; j++)
			cout << ans[i][j] << " ";
		cout << "\n";
	}
}
int main()
{
	ios_base::sync_with_stdio(false), cin.tie(0);
	int n;
	cin >> n;
	vector<int>v(n + 1, 0);
	map<int, int>mp;
	for(int i = 1; i <= n; i++)
	{
		cin >> v[i];
		mp[v[i]]++;
	}

	int mx = 0;
	int cur = 1;
	vector<int>vec;
	for(auto aa : mp)
	{
		se.insert({-aa.y, aa.x});
		for(int i = 1; i <= aa.y; i++)
			vec.pb(i);
		mx = max(mx, aa.y);
		cur++;
	}

	sort(all(v));
	int besth = 0, bestw = 0;
	for(int i = 1; i <= mx; i++)
	{
		int l = 1, r = n / i;
		while(l < r)
		{
			int mid = (l + r + 1) / 2;
			if(upper_bound(all(vec), mid) - vec.begin() >= 1ll * mid * i)
				l = mid;
			else
				r = mid - 1;
		}
		if(l >= i)
		{
			if(i * l >= besth * bestw)
				besth = i, bestw = l;
		}
	}

	construct(besth, bestw);
	return 0;
}


/*input
5
1 1 1 1 1
*/
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define pb push_back
#define x first
#define y second
#define all(a) a.begin(), a.end()
#define sz(a) (int)a.size()
#define rd() abs((int)rng())
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
const int maxn = 4e5 + 100;
const int mod = 1e9 + 7;
mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());
set<pii>se;
void construct(int h, int w)
{
	cout << h * w << "\n";
	cout << h << " " << w << "\n";
	int cur = 0;
	vector<vector<int> >ans(h + 5, vector<int>(w + 5, 0));
	for(pii p : se)
	{
		int cnt = min(-p.x, h);
		while(cnt > 0)
		{
			int col = cur % w;
			int row = (cur / w + cur % w) % h;
			ans[row][col] = p.y;
			cur++;
			cnt--;
		}
	}
	for(int i = 0; i < h; i++)
	{
		for(int j = 0; j < w; j++)
			cout << ans[i][j] << " ";
		cout << "\n";
	}
}
int main()
{
	ios_base::sync_with_stdio(false), cin.tie(0);
	int n;
	cin >> n;
	vector<int>v(n + 1, 0);
	map<int, int>mp;
	for(int i = 1; i <= n; i++)
	{
		cin >> v[i];
		mp[v[i]]++;
	}

	int mx = 0;
	int cur = 1;
	vector<int>vec;
	for(auto aa : mp)
	{
		se.insert({-aa.y, aa.x});
		for(int i = 1; i <= aa.y; i++)
			vec.pb(i);
		mx = max(mx, aa.y);
		cur++;
	}

	sort(all(vec));

	int besth = 0, bestw = 0;
	for(int h = 1; h * h <= n; h++)
	{
		int w = (upper_bound(all(vec), h) - vec.begin()) / h;
		if(w >= h)
		{
			if(h * w >= besth * bestw)
				besth = h, bestw = w;
		}
	}

	construct(besth, bestw);
	return 0;
}


/*input
20
1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 5 6 7 8
*/
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define pb push_back
#define x first
#define y second
#define all(a) a.begin(), a.end()
#define sz(a) (int)a.size()
#define rd() abs((int)rng())
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
const int maxn = 4e5 + 100;
const int mod = 1e9 + 7;
mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());
set<pii>se;
void construct(int h, int w)
{
	cout << h * w << "\n";
	cout << h << " " << w << "\n";
	int cur = 0;
	vector<vector<int> >ans(h + 5, vector<int>(w + 5, 0));
	int now = 0;
	for(pii p : se)
	{
		int cnt = min(-p.x, h);
		while(cnt > 0)
		{
			int col = cur % w;
			if(col == 0)
				now = cur / w;
			int row = now % h;
			ans[row][col] = p.y;
			cur++;
			cnt--;
			now++;
		}
	}
	for(int i = 0; i < h; i++)
	{
		for(int j = 0; j < w; j++)
			cout << ans[i][j] << " ";
		cout << "\n";
	}
}
int main()
{
	ios_base::sync_with_stdio(false), cin.tie(0);
	int n;
	cin >> n;
	vector<int>v(n + 1, 0);
	map<int, int>mp;
	for(int i = 1; i <= n; i++)
	{
		cin >> v[i];
		mp[v[i]]++;
	}

	int mx = 0;
	int cur = 1;
	vector<int>vec;
	for(auto aa : mp)
	{
		se.insert({-aa.y, aa.x});
		for(int i = 1; i <= aa.y; i++)
			vec.pb(i);
		mx = max(mx, aa.y);
		cur++;
	}

	sort(all(v));
	int besth = 0, bestw = 0;
	for(int i = 1; i <= mx; i++)
	{
		int l = 1, r = n / i;
		while(l < r)
		{
			int mid = (l + r + 1) / 2;
			if(upper_bound(all(vec), i) - vec.begin() >= 1ll * mid * i)
				l = mid;
			else
				r = mid - 1;
		}
		if(l >= i)
		{
			if(i * l >= besth * bestw)
				besth = i, bestw = l;
		}
	}

	construct(besth, bestw);
	return 0;
}


/*input
9
1 2 3 1 2 3 1 1 2
*/
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define pb push_back
#define x first
#define y second
#define all(a) a.begin(), a.end()
#define sz(a) (int)a.size()
#define rd() abs((int)rng())
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
const int maxn = 4e5 + 100;
const int mod = 1e9 + 7;
mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());
set<pii>se;
void construct(int h, int w)
{
	cout << h * w << "\n";
	cout << h << " " << w << "\n";
	int cx = 0, cy = 0;
	set<int>avail[w + 1];
	for(int j = 1; j <= w; j++)
	{
		for(int i = 1; i <= h; i++)
			avail[j].insert(i);
	}
	vector<vector<int> >ans(h + 2, vector<int>(w + 2, 0));
	for(pii p : se)
	{
		int cnt = min(-p.x, h);
		while(cnt > 0)
		{
			while(ans[cx][cy] != 0)
				cx = *avail[cy].begin();
			ans[cx][cy] = p.y;
			avail[cy].erase(cx);
			cx = (cx + 1) % h;
			cy = (cy + 1) % w;
			cnt--;
		}
	}
	for(int i = 0; i < h; i++)
	{
		set<int>st;
		for(int j = 0; j < w; j++)
		{
			if(st.count(ans[i][j]))
				assert(false);
			st.insert(ans[i][j]);
		}
	}
	for(int j = 0; j < w; j++)
	{
		set<int>st;
		for(int i = 0; i < h; i++)
		{
			if(st.count(ans[i][j]))
				assert(false);
			st.insert(ans[i][j]);
		}
	}
	for(int i = 0; i < h; i++)
	{
		for(int j = 0; j < w; j++)
			cout << ans[i][j] << " ";
		cout << "\n";
	}
}
int main()
{
	ios_base::sync_with_stdio(false), cin.tie(0);
	int n;
	cin >> n;
	vector<int>v(n + 1, 0);
	map<int, int>mp;
	for(int i = 1; i <= n; i++)
	{
		cin >> v[i];
		mp[v[i]]++;
	}

	vector<int>vec;
	for(auto aa : mp)
	{
		se.insert({-aa.y, aa.x});
		for(int i = 1; i <= aa.y; i++)
			vec.pb(i);
	}

	sort(all(vec));

	int besth = 0, bestw = 0;
	for(int h = 1; h * h <= n; h++)
	{
		int w = (upper_bound(all(vec), h) - vec.begin()) / h;
		if(w >= h)
		{
			if(h * w >= besth * bestw)
				besth = h, bestw = w;
		}
	}

	construct(besth, bestw);
	return 0;
}


/*input
9
1 2 3 1 2 3 1 1 2
*/
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define pb push_back
#define x first
#define y second
#define all(a) a.begin(), a.end()
#define sz(a) (int)a.size()
#define rd() abs((int)rng())
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
const int maxn = 4e5 + 100;
const int mod = 1e9 + 7;
mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());
set<pii>se;
void construct(int h, int w)
{
	cout << h * w << "\n";
	cout << h << " " << w << "\n";
	int cx = 0, cy = 0;
	vector<vector<int> >ans(h + 2, vector<int>(w + 2, 0));
	for(pii p : se)
	{
		int cnt = min(-p.x, h);
		while(cnt > 0)
		{
			while(ans[cx][cy] != 0)
				cx = (cx + 1) % h;
			ans[cx][cy] = p.y;
			cx = (cx + 1) % h;
			cy = (cy + 1) % w;
			cnt--;
		}
	}
	for(int i = 0; i < h; i++)
	{
		set<int>st;
		for(int j = 0; j < w; j++)
		{
			if(st.count(ans[i][j]))
				assert(false);
			st.insert(ans[i][j]);
		}
	}
	for(int j = 0; j < w; j++)
	{
		set<int>st;
		for(int i = 0; i < h; i++)
		{
			if(st.count(ans[i][j]))
				assert(false);
			st.insert(ans[i][j]);
		}
	}
	for(int i = 0; i < h; i++)
	{
		for(int j = 0; j < w; j++)
			cout << ans[i][j] << " ";
		cout << "\n";
	}
}
int main()
{
	ios_base::sync_with_stdio(false), cin.tie(0);
	int n;
	cin >> n;
	vector<int>v(n + 1, 0);
	map<int, int>mp;
	for(int i = 1; i <= n; i++)
	{
		cin >> v[i];
		mp[v[i]]++;
	}

	vector<int>vec;
	for(auto aa : mp)
	{
		se.insert({-aa.y, aa.x});
		for(int i = 1; i <= aa.y; i++)
			vec.pb(i);
	}

	sort(all(vec));

	int besth = 0, bestw = 0;
	for(int h = 1; h * h <= n; h++)
	{
		int w = (upper_bound(all(vec), h) - vec.begin()) / h;
		if(w >= h)
		{
			if(h * w >= besth * bestw)
				besth = h, bestw = w;
		}
	}

	construct(besth, bestw);
	return 0;
}


/*input
5
1 1 1 1 1
*/
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define pb push_back
#define x first
#define y second
#define all(a) a.begin(), a.end()
#define sz(a) (int)a.size()
#define rd() abs((int)rng())
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
const int maxn = 4e5 + 100;
const int mod = 1e9 + 7;
mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());
template<class T> using ordered_set = tree<T, null_type, greater_equal<T>, rb_tree_tag, tree_order_statistics_node_update>;
set<pii>se;
bool can(int h)
{
	int tot = 0;
	for(pii p : se)
		tot += min(-p.x, h);
	int w = 1;
	while(h * (w + 1) <= tot)
		w++;
	if(w < h)
		return false;
	return true;
}
void construct(int h)
{
	int w = h;
	int tot = 0;
	for(pii p : se)
		tot += min(-p.x, h);
	while(h * (w + 1) <= tot)
		w++;
	cout << h * w << "\n";
	cout << h << " " << w << "\n";
	int cur = 0;
	vector<vector<int> >ans(h + 5, vector<int>(w + 5, 0));
	for(pii p : se)
	{
		int cnt = min(-p.x, h);
		while(cnt > 0)
		{
			int col = cur % w;
			int row = (cur % h + cur / w) % h;
			ans[row][col] = p.y;
			cur++;
			cnt--;
		}
	}
	for(int i = 0; i < h; i++)
	{
		for(int j = 0; j < w; j++)
			cout << ans[i][j] << " ";
		cout << "\n";
	}
}
int main()
{
	ios_base::sync_with_stdio(false), cin.tie(0);
	int n;
	cin >> n;
	vector<int>v(n + 1, 0);
	map<int, int>mp;
	for(int i = 1; i <= n; i++)
	{
		cin >> v[i];
		mp[v[i]]++;
	}

	int mx = 0;
	for(auto aa : mp)
	{
		mx = max(mx, aa.y);
		se.insert({-aa.y, aa.x});
	}

	int lo = 1, hi = mx;
	while(lo < hi)
	{
		int mid = (lo + hi + 1) / 2;
		if(can(mid))
			lo = mid;
		else
			hi = mid - 1;
	}
	construct(lo);
	return 0;
}


/*input
9
1 2 3 1 2 3 1 1 2
*/
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define pb push_back
#define x first
#define y second
#define all(a) a.begin(), a.end()
#define sz(a) (int)a.size()
#define rd() abs((int)rng())
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
const int maxn = 4e5 + 100;
const int mod = 1e9 + 7;
mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());
set<pii>se;
void construct(int h, int w)
{
	cout << h * w << "\n";
	cout << h << " " << w << "\n";
	int cx = 0, cy = 0;
	set<int>avail[w + 1];
	for(int j = 0; j < w; j++)
	{
		for(int i = 0; i < h; i++)
			avail[j].insert(i);
	}
	vector<vector<int> >ans(h + 2, vector<int>(w + 2, 0));
	for(pii p : se)
	{
		int cnt = min(-p.x, h);
		while(cnt > 0)
		{
			if(ans[cx][cy] != 0)
				cx = *avail[cy].begin();
			ans[cx][cy] = p.y;
			avail[cy].erase(cx);
			cx = (cx + 1) % h;
			cy = (cy + 1) % w;
			cnt--;
		}
	}
	for(int i = 0; i < h; i++)
	{
		set<int>st;
		for(int j = 0; j < w; j++)
		{
			if(st.count(ans[i][j]))
				assert(false);
			st.insert(ans[i][j]);
		}
	}
	for(int j = 0; j < w; j++)
	{
		set<int>st;
		for(int i = 0; i < h; i++)
		{
			if(st.count(ans[i][j]))
				assert(false);
			st.insert(ans[i][j]);
		}
	}
	for(int i = 0; i < h; i++)
	{
		for(int j = 0; j < w; j++)
			cout << ans[i][j] << " ";
		cout << "\n";
	}
}
int main()
{
	ios_base::sync_with_stdio(false), cin.tie(0);
	int n;
	cin >> n;
	vector<int>v(n + 1, 0);
	map<int, int>mp;
	for(int i = 1; i <= n; i++)
	{
		cin >> v[i];
		mp[v[i]]++;
	}

	vector<int>vec;
	for(auto aa : mp)
	{
		se.insert({-aa.y, aa.x});
		for(int i = 1; i <= aa.y; i++)
			vec.pb(i);
	}

	sort(all(vec));

	int besth = 0, bestw = 0;
	for(int h = 1; h * h <= n; h++)
	{
		int w = (upper_bound(all(vec), h) - vec.begin()) / h;
		if(w >= h)
		{
			if(h * w >= besth * bestw)
				besth = h, bestw = w;
		}
	}

	construct(besth, bestw);
	return 0;
}


/*input
9
1 2 3 1 2 3 1 1 2
*/
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define pb push_back
#define x first
#define y second
#define all(a) a.begin(), a.end()
#define sz(a) (int)a.size()
#define rd() abs((int)rng())
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
const int maxn = 4e5 + 100;
const int mod = 1e9 + 7;
mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());
set<pii>se;
void construct(int h, int w)
{
	cout << h * w << "\n";
	cout << h << " " << w << "\n";
	int cx = 0, cy = 0;
	vector<vector<int> >ans(h + 2, vector<int>(w + 2, 0));
	for(pii p : se)
	{
		int cnt = min(-p.x, h);
		while(cnt > 0)
		{
			if(ans[cx][cy] != 0)
				cx = (cx + 1) % h;
			ans[cx][cy] = p.y;
			cx = (cx + 1) % h;
			cy = (cy + 1) % w;
			cnt--;
		}
	}
	for(int i = 0; i < h; i++)
	{
		for(int j = 0; j < w; j++)
			cout << ans[i][j] << " ";
		cout << "\n";
	}
}
int main()
{
	ios_base::sync_with_stdio(false), cin.tie(0);
	int n;
	cin >> n;
	vector<int>v(n + 1, 0);
	map<int, int>mp;
	for(int i = 1; i <= n; i++)
	{
		cin >> v[i];
		mp[v[i]]++;
	}

	vector<int>vec;
	for(auto aa : mp)
	{
		se.insert({-aa.y, aa.x});
		for(int i = 1; i <= aa.y; i++)
			vec.pb(i);
	}

	sort(all(vec));

	int besth = 0, bestw = 0;
	for(int h = 1; h * h <= n; h++)
	{
		int w = (upper_bound(all(vec), h) - vec.begin()) / h;
		if(w >= h)
		{
			if(h * w >= besth * bestw)
				besth = h, bestw = w;
		}
	}

	construct(besth, bestw);
	return 0;
}


/*input
9
1 2 3 1 2 3 1 1 2
*/
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define pb push_back
#define x first
#define y second
#define all(a) a.begin(), a.end()
#define sz(a) (int)a.size()
#define rd() abs((int)rng())
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
const int maxn = 4e5 + 100;
const int mod = 1e9 + 7;
mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());
set<pii>se;
void construct(int h, int w)
{
	cout << h * w << "\n";
	cout << h << " " << w << "\n";
	int cx = 0, cy = 0;
	vector<vector<int> >ans(h + 2, vector<int>(w + 2, 0));
	for(pii p : se)
	{
		int cnt = min(-p.x, h);
		while(cnt > 0)
		{
			if(ans[cx][cy] != 0)
				cx = (cx + 1) % h;
			ans[cx][cy] = p.y;
			cx = (cx + 1) % h;
			cy = (cy + 1) % w;
			cnt--;
		}
	}
	for(int i = 0; i < h; i++)
	{
		set<int>st;
		for(int j = 0; j < w; j++)
		{
			if(st.count(ans[i][j]))
				assert(false);
			st.insert(ans[i][j]);
		}
	}
	for(int j = 0; j < w; j++)
	{
		set<int>st;
		for(int i = 0; i < h; i++)
		{
			if(st.count(ans[i][j]))
				assert(false);
			st.insert(ans[i][j]);
		}
	}
	for(int i = 0; i < h; i++)
	{
		for(int j = 0; j < w; j++)
			cout << ans[i][j] << " ";
		cout << "\n";
	}
}
int main()
{
	ios_base::sync_with_stdio(false), cin.tie(0);
	int n;
	cin >> n;
	vector<int>v(n + 1, 0);
	map<int, int>mp;
	for(int i = 1; i <= n; i++)
	{
		cin >> v[i];
		mp[v[i]]++;
	}

	vector<int>vec;
	for(auto aa : mp)
	{
		se.insert({-aa.y, aa.x});
		for(int i = 1; i <= aa.y; i++)
			vec.pb(i);
	}

	sort(all(vec));

	int besth = 0, bestw = 0;
	for(int h = 1; h * h <= n; h++)
	{
		int w = (upper_bound(all(vec), h) - vec.begin()) / h;
		if(w >= h)
		{
			if(h * w >= besth * bestw)
				besth = h, bestw = w;
		}
	}

	construct(besth, bestw);
	return 0;
}


/*input
9
3 1 4 1 5 9 2 6 5
*/
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define pb push_back
#define x first
#define y second
#define all(a) a.begin(), a.end()
#define sz(a) (int)a.size()
#define rd() abs((int)rng())
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
const int maxn = 4e5 + 100;
const int mod = 1e9 + 7;
mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());
set<pii>se;
void construct(int h, int w)
{
	cout << h * w << "\n";
	cout << h << " " << w << "\n";
	int cur = 0;
	vector<vector<int> >ans(h + 5, vector<int>(w + 5, 0));
	int now = 0;
	for(pii p : se)
	{
		int cnt = min(-p.x, h);
		while(cnt > 0)
		{
			int col = cur % w;
			int row = (cur / w + cur % w) % h;
			ans[row][col] = p.y;
			cur++;
			cnt--;
			now++;
		}
	}
	for(int i = 0; i < h; i++)
	{
		for(int j = 0; j < w; j++)
			cout << ans[i][j] << " ";
		cout << "\n";
	}
}
int main()
{
	ios_base::sync_with_stdio(false), cin.tie(0);
	int n;
	cin >> n;
	vector<int>v(n + 1, 0);
	map<int, int>mp;
	for(int i = 1; i <= n; i++)
	{
		cin >> v[i];
		mp[v[i]]++;
	}

	int mx = 0;
	int cur = 1;
	vector<int>vec;
	for(auto aa : mp)
	{
		se.insert({-aa.y, aa.x});
		for(int i = 1; i <= aa.y; i++)
			vec.pb(i);
		mx = max(mx, aa.y);
		cur++;
	}

	sort(all(vec));

	int besth = 0, bestw = 0;
	for(int h = 1; h <= mx; h++)
	{
		int w = (upper_bound(all(vec), h) - vec.begin()) / h;
		if(w >= h)
		{
			if(h * w >= besth * bestw)
				besth = h, bestw = w;
		}
	}

	construct(besth, bestw);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;

typedef long long int ll;
typedef unsigned long long int ull;
ll power(ll x,ll y,ll p){ll r=1; x=x%p; while(y>0){ if(y&1) r= r*x%p; y=y>>1; x=x*x%p; } return r; }

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
typedef tree<int, null_type, less_equal<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
int csrand(int l=0, int r=1e9){
    uniform_int_distribution<int> uid(l, r);
    return uid(rng);
}

#define PR(x) cout<<#x<<" : "<<x<<"\n";
#define PR1(x,y) cout<<#x<<" : "<<x<<"  |  "<<#y<<" : "<<y<<"\n";
#define PR2(x,y,z) cout<<#x<<" : "<<x<<"  |  "<<#y<<" : "<<y<<"  |  "<<#z<<" : "<<z<<"\n";
#define ED cout<<'\n';

#define IO              ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define FILEIO          freopen("input.txt", "r", stdin);freopen("output.txt", "w", stdout);
#define all(v)          v.begin(),v.end()
#define endl            '\n'
#define fr1(j,n)        for(int j=0;j<n;j++)
// #define fr(n)           for(int i=0;i<n;i++)
#define PB              push_back
#define pii             pair<int,int>
#define pll             pair<long long int,long long int>
#define F               first
#define S               second

const ll mod=1e9+7;
const ll mod9=998244353;
const int N=4e5+99;

ll arr[N],sum[N];
vector<ll> fq;

ll chk(ll rr,ll cc)
{
    ll mi=min(rr,cc);
    ll ii=upper_bound(all(fq),mi)-fq.begin();

    ll tot=sum[ii-1];
    ll ss=(fq.size()-ii);
    tot = ss*mi + tot;
    return tot;
}

int main()
{
    IO
    #ifndef ONLINE_JUDGE
    FILEIO
    #endif

    ll n;
    cin>>n;
    map<ll,ll> mp;

    ll mx=0,sz=0;
    fr1(i,n)
    {
        cin>>arr[i];
        mp[arr[i]]++;
        mx=max(mx,mp[arr[i]]);
    }

    sz=mp.size();
    for(auto x:mp) fq.PB(x.S);
    sort(all(fq));

    for(int i=0;i<sz;i++)
    {
        sum[i]=fq[i];
        if(i) sum[i]+=sum[i-1];
    }

    ll fc=1,fr=1,ar=1;
    for(ll rr=1;rr<=min(sz,n);rr++)
    {

        ll lo=1,hi=n/rr,mi,ans;

        while(lo<=hi)
        {
            mi=(lo+hi)/2;

            if( sz>=(ll)max(rr,mi) && chk(rr,mi)>=rr*mi)
                ans=mi,
                lo=mi+1;
            else
                hi=mi-1;
        }
        if(rr*ans > ar)
        {
            ar=rr*ans;
            fr=rr;
            fc=ans;
        }
    }

    if(fr>fc) swap(fr,fc);

    ll ans[fr][fc];

    fr1(i,fr)fr1(j,fc)ans[i][j]=0;

    cout<<fr*fc<<endl;
    cout<<fr<<" "<<fc<<endl;
    vector<pii> pos;

    for(int c=0;c<fc;c++)
    {
        int r=0;
        for(int i=0;i<fr;i++)
        {
            pos.PB({i+r,(c+i)%fc});
        }
    }
    reverse(all(pos));

    for(auto x:mp)
    {
        fr1(i,min(x.S,fr))
        {
            if(pos.empty()) break;
            auto xx=pos.back();
            pos.pop_back();
            ans[xx.F][xx.S]=x.F;
        }
        if(pos.empty()) break;
    }

    fr1(i,fr)
    {
        fr1(j,fc)
        cout<<ans[i][j]<<" ";
        ED
    }

}


#include <bits/stdc++.h>
using namespace std;

typedef long long int ll;
typedef unsigned long long int ull;
ll power(ll x,ll y,ll p){ll r=1; x=x%p; while(y>0){ if(y&1) r= r*x%p; y=y>>1; x=x*x%p; } return r; }

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
typedef tree<int, null_type, less_equal<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
int csrand(int l=0, int r=1e9){
    uniform_int_distribution<int> uid(l, r);
    return uid(rng);
}

#define PR(x) cout<<#x<<" : "<<x<<"\n";
#define PR1(x,y) cout<<#x<<" : "<<x<<"  |  "<<#y<<" : "<<y<<"\n";
#define PR2(x,y,z) cout<<#x<<" : "<<x<<"  |  "<<#y<<" : "<<y<<"  |  "<<#z<<" : "<<z<<"\n";
#define ED cout<<'\n';

#define IO              ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define FILEIO          freopen("input.txt", "r", stdin);freopen("output.txt", "w", stdout);
#define all(v)          v.begin(),v.end()
#define endl            '\n'
#define fr1(j,n)        for(int j=0;j<n;j++)
// #define fr(n)           for(int i=0;i<n;i++)
#define PB              push_back
#define pii             pair<int,int>
#define pll             pair<long long int,long long int>
#define F               first
#define S               second

const ll mod=1e9+7;
const ll mod9=998244353;
const int N=4e5+99;

ll arr[N],sum[N];
vector<ll> fq;

ll chk(ll rr,ll cc)
{
    ll mi=min(rr,cc);
    ll ii=upper_bound(all(fq),mi)-fq.begin();

    ll tot=0;
    if(ii) tot=sum[ii-1];
    ll ss=(fq.size()-ii);
    tot = ss*mi + tot;
    return tot;
}

int main()
{
    IO
    #ifndef ONLINE_JUDGE
    FILEIO
    #endif

    ll n;
    cin>>n;
    map<ll,ll> mp;

    ll mx=0,sz=0;
    fr1(i,n)
    {
        cin>>arr[i];
        mp[arr[i]]++;
        mx=max(mx,mp[arr[i]]);
    }

    sz=mp.size();
    for(auto x:mp) fq.PB(x.S);
    sort(all(fq));

    for(int i=0;i<sz;i++)
    {
        sum[i]=fq[i];
        if(i) sum[i]+=sum[i-1];
    }

    ll fc=1,fr=1,ar=1;
    for(ll rr=1;rr<=min(n,n);rr++)
    {

        ll lo=0,hi=n/rr,mi,ans=0;

        while(lo<=hi)
        {
            mi=(lo+hi)/2;

            if( sz>=(ll)max(rr,mi) && chk(rr,mi)>=rr*mi)
                ans=mi,
                lo=mi+1;
            else
                hi=mi-1;
        }
        if(rr*ans > ar)
        {
            ar=rr*ans;
            fr=rr;
            fc=ans;
        }
    }

    if(fr>fc) swap(fr,fc);

    ll ans[fr][fc];

    vector<pii> pos;

    for(int c=0;c<fc;c++)
    {
        for(int i=0;i<fr;i++)
        {
            pos.PB({i,(c+i)%fc});
        }
    }

    reverse(all(pos));

    vector<pll> pp;
    for(auto x:mp) pp.PB({x.S,x.F});
    sort(all(pp));
    reverse(all(pp));

    for(auto x:pp)
    {
        fr1(i,min(x.F,fr))
        {
            if(pos.empty()) break;
            auto xx=pos.back();
            pos.pop_back();
            ans[xx.F][xx.S]=x.S;
        }
        if(pos.empty()) break;
    }

    cout<<(ll)(fr*fc)<<endl;
    cout<<fr<<" "<<fc<<endl;
    fr1(i,fr)
    {
        fr1(j,fc)
        cout<<ans[i][j]<<" ";
        ED
    }

}


#include <bits/stdc++.h>
using namespace std;

typedef long long int ll;
typedef unsigned long long int ull;
ll power(ll x,ll y,ll p){ll r=1; x=x%p; while(y>0){ if(y&1) r= r*x%p; y=y>>1; x=x*x%p; } return r; }

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
typedef tree<int, null_type, less_equal<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
int csrand(int l=0, int r=1e9){
    uniform_int_distribution<int> uid(l, r);
    return uid(rng);
}

#define PR(x) cout<<#x<<" : "<<x<<"\n";
#define PR1(x,y) cout<<#x<<" : "<<x<<"  |  "<<#y<<" : "<<y<<"\n";
#define PR2(x,y,z) cout<<#x<<" : "<<x<<"  |  "<<#y<<" : "<<y<<"  |  "<<#z<<" : "<<z<<"\n";
#define ED cout<<'\n';

#define IO              ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define FILEIO          freopen("input.txt", "r", stdin);freopen("output.txt", "w", stdout);
#define all(v)          v.begin(),v.end()
#define endl            '\n'
#define fr1(j,n)        for(int j=0;j<n;j++)
// #define fr(n)           for(int i=0;i<n;i++)
#define PB              push_back
#define pii             pair<int,int>
#define pll             pair<long long int,long long int>
#define F               first
#define S               second

const ll mod=1e9+7;
const ll mod9=998244353;
const int N=2e5+99;

ll arr[N],sum[N];
vector<ll> fq;

ll chk(ll rr,ll cc)
{
    ll mi=min(rr,cc);
    ll ii=upper_bound(all(fq),mi)-fq.begin();

    ll tot=sum[ii-1];
    ll ss=(fq.size()-ii);
    tot = ss*mi + tot;
    return tot;
}

int main()
{
    IO
    #ifndef ONLINE_JUDGE
    FILEIO
    #endif

    ll n;
    cin>>n;
    map<ll,ll> mp;

    ll mx=0,sz=0;
    fr1(i,n)
    {
        cin>>arr[i];
        mp[arr[i]]++;
        mx=max(mx,mp[arr[i]]);
    }

    sz=mp.size();
    for(auto x:mp) fq.PB(x.S);
    sort(all(fq));

    for(int i=0;i<sz;i++)
    {
        sum[i]=fq[i];
        if(i) sum[i]+=sum[i-1];
    }

    ll fc=1,fr=1,ar=1;
    for(ll rr=1;rr<=min(sz,n);rr++)
    {

        ll lo=1,hi=n/rr,mi,ans;

        while(lo<=hi)
        {
            mi=(lo+hi)/2;

            if( sz>=(ll)max(rr,mi) && chk(rr,mi)>=rr*mi)
                ans=mi,
                lo=mi+1;
            else
                hi=mi-1;
        }
        if(rr*ans > ar)
        {
            ar=rr*ans;
            fr=rr;
            fc=ans;
        }
    }

    if(fr>fc) swap(fr,fc);

    ll ans[fr][fc];

    fr1(i,fr)fr1(j,fc)ans[i][j]=0;

    cout<<fr*fc<<endl;
    cout<<fr<<" "<<fc<<endl;
    vector<pii> pos;

    for(int c=0;c<fc;c++)
    {
        int r=0;
        for(int i=0;i<fr;i++)
        {
            pos.PB({i+r,(c+i)%fc});
        }
    }
    reverse(all(pos));

    for(auto x:mp)
    {
        fr1(i,min(x.S,fr))
        {
            if(pos.empty()) break;
            auto xx=pos.back();
            pos.pop_back();
            ans[xx.F][xx.S]=x.F;
        }
        if(pos.empty()) break;
    }

    fr1(i,fr)
    {
        fr1(j,fc)
        cout<<ans[i][j]<<" ";
        ED
    }

}


#include <bits/stdc++.h>
using namespace std;

typedef long long int ll;
typedef unsigned long long int ull;
ll power(ll x,ll y,ll p){ll r=1; x=x%p; while(y>0){ if(y&1) r= r*x%p; y=y>>1; x=x*x%p; } return r; }

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
typedef tree<int, null_type, less_equal<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
int csrand(int l=0, int r=1e9){
    uniform_int_distribution<int> uid(l, r);
    return uid(rng);
}

#define PR(x) cout<<#x<<" : "<<x<<"\n";
#define PR1(x,y) cout<<#x<<" : "<<x<<"  |  "<<#y<<" : "<<y<<"\n";
#define PR2(x,y,z) cout<<#x<<" : "<<x<<"  |  "<<#y<<" : "<<y<<"  |  "<<#z<<" : "<<z<<"\n";
#define ED cout<<'\n';

#define IO              ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define FILEIO          freopen("input.txt", "r", stdin);freopen("output.txt", "w", stdout);
#define all(v)          v.begin(),v.end()
#define endl            '\n'
#define fr1(j,n)        for(int j=0;j<n;j++)
// #define fr(n)           for(int i=0;i<n;i++)
#define PB              push_back
#define pii             pair<int,int>
#define pll             pair<long long int,long long int>
#define F               first
#define S               second

const ll mod=1e9+7;
const ll mod9=998244353;
const int N=4e5+99;

ll arr[N],sum[N];
vector<ll> fq;

ll chk(ll rr,ll cc)
{
    ll mi=min(rr,cc);
    ll ii=upper_bound(all(fq),mi)-fq.begin();

    ll tot=0;
    if(ii) tot=sum[ii-1];
    ll ss=(fq.size()-ii);
    tot = ss*mi + tot;
    return tot;
}

int main()
{
    IO
    #ifndef ONLINE_JUDGE
    FILEIO
    #endif

    ll n;
    cin>>n;
    map<ll,ll> mp;

    ll mx=0,sz=0;
    fr1(i,n)
    {
        cin>>arr[i];
        mp[arr[i]]++;
        mx=max(mx,mp[arr[i]]);
    }

    sz=mp.size();
    for(auto x:mp) fq.PB(x.S);
    sort(all(fq));

    for(int i=0;i<sz;i++)
    {
        sum[i]=fq[i];
        if(i) sum[i]+=sum[i-1];
    }

    ll fc=1,fr=1,ar=1;
    for(ll rr=1;rr<=min(sz,n);rr++)
    {

        ll lo=1,hi=n/rr,mi,ans=-1;

        while(lo<=hi)
        {
            mi=(lo+hi)/2;

            if( sz>=(ll)max(rr,mi) && chk(rr,mi)>=rr*mi)
                ans=mi,
                lo=mi+1;
            else
                hi=mi-1;
        }
        if(rr*ans > ar)
        {
            ar=rr*ans;
            fr=rr;
            fc=ans;
        }
    }

    if(fr>fc) swap(fr,fc);

    ll ans[fr][fc];

    fr1(i,fr)fr1(j,fc)ans[i][j]=0;

    vector<pii> pos;

    for(int c=0;c<fc;c++)
    {
        int r=0;
        for(int i=0;i<fr;i++)
        {
            pos.PB({i+r,(c+i)%fc});
        }
    }
    reverse(all(pos));

    for(auto x:mp)
    {
        fr1(i,min(x.S,fr))
        {
            if(pos.empty()) break;
            auto xx=pos.back();
            pos.pop_back();
            ans[xx.F][xx.S]=x.F;
        }
        if(pos.empty()) break;
    }

    cout<<(ll)(fr*fc)<<endl;
    cout<<fr<<" "<<fc<<endl;
    fr1(i,fr)
    {
        fr1(j,fc)
        cout<<ans[i][j]<<" ";
        ED
    }

}


#include <bits/stdc++.h>
using namespace std;

typedef long long int ll;
typedef unsigned long long int ull;
ll power(ll x,ll y,ll p){ll r=1; x=x%p; while(y>0){ if(y&1) r= r*x%p; y=y>>1; x=x*x%p; } return r; }

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
typedef tree<int, null_type, less_equal<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
int csrand(int l=0, int r=1e9){
    uniform_int_distribution<int> uid(l, r);
    return uid(rng);
}

#define PR(x) cout<<#x<<" : "<<x<<"\n";
#define PR1(x,y) cout<<#x<<" : "<<x<<"  |  "<<#y<<" : "<<y<<"\n";
#define PR2(x,y,z) cout<<#x<<" : "<<x<<"  |  "<<#y<<" : "<<y<<"  |  "<<#z<<" : "<<z<<"\n";
#define ED cout<<'\n';

#define IO              ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define FILEIO          freopen("input.txt", "r", stdin);freopen("output.txt", "w", stdout);
#define all(v)          v.begin(),v.end()
#define endl            '\n'
#define fr1(j,n)        for(int j=0;j<n;j++)
// #define fr(n)           for(int i=0;i<n;i++)
#define PB              push_back
#define pii             pair<int,int>
#define pll             pair<long long int,long long int>
#define F               first
#define S               second

const ll mod=1e9+7;
const ll mod9=998244353;
const int N=2e5+99;

ll arr[N],sum[N];
vector<ll> fq;

ll chk(ll rr,ll cc)
{
    ll mi=min(rr,cc);
    ll ii=upper_bound(all(fq),mi)-fq.begin();

    ll tot=sum[ii-1];
    ll ss=(fq.size()-ii);
    tot = ss*mi + tot;
    return tot;
}

int main()
{
    IO
    #ifndef ONLINE_JUDGE
    FILEIO
    #endif

    ll n;
    cin>>n;
    map<ll,ll> mp;

    ll mx=0,sz=0;
    fr1(i,n)
    {
        cin>>arr[i];
        mp[arr[i]]++;
        mx=max(mx,mp[arr[i]]);
    }

    sz=mp.size();
    for(auto x:mp) fq.PB(x.S);
    sort(all(fq));

    for(int i=0;i<sz;i++)
    {
        sum[i]=fq[i];
        if(i) sum[i]+=sum[i-1];
    }

    ll fc=1,fr=1,ar=1;
    for(ll rr=1;rr<=min(sz,n);rr++)
    {

        ll lo=1,hi=n/rr,mi,ans;

        while(lo<=hi)
        {
            mi=(lo+hi)/2;

            if( sz>=(ll)max(rr,mi) && chk(rr,mi)>=rr*mi)
                ans=mi,
                lo=mi+1;
            else
                hi=mi-1;
        }
        if(rr*ans > ar)
        {
            ar=rr*ans;
            fr=rr;
            fc=ans;
        }
    }

    if(fr>fc) swap(fr,fc);

    ll ans[fr][fc];

    fr1(i,fr)fr1(j,fc)ans[i][j]=0;

    map<ll,ll> vis;

    ll r1=0,c1=0;
    vector<ll> lft;
    for(auto x:mp)
    {
        if(x.S >=fr)
        {
            for(int i=0;i<fr;i++)
                ans[(r1+i)%fr][(c1+i)%fc]=x.F;
            vis[x.F]=1;
            c1++;
        }
        else
        {
            fr1(j,x.S) lft.PB(x.F);

        }
    }

    cout<<fr*fc<<endl;
    cout<<fr<<" "<<fc<<endl;
    for(int i=0;i<fr;i++)
    {
        for(int j=0;j<fc;j++)
        {
            if(ans[i][j]==0)
            {
                cout<<lft.back()<<" ";
                lft.pop_back();
            }
            else
                cout<<ans[i][j]<<" ";
        }
        ED
    }

}