#include <bits/stdc++.h>
using namespace std;
int main() {
  int n;
  scanf("%d", &n);
  int a[n];
  unordered_map<int, int> ct;
  for (int i = 0; i < n; i++) {
    scanf("%d", &a[i]);
    ct[a[i]]++;
  }
  sort(a, a + n);
  vector<pair<int, int> > v;
  for (int i = 0; i < n; i++) {
    if (i == 0 || a[i] != a[i - 1]) v.push_back({ct[a[i]], a[i]});
  }
  sort(v.begin(), v.end());
  int vs = (int)v.size();
  int num = 0;
  int best = 0;
  int besx = 0;
  int id = 0;
  for (int i = 1; i * i <= n; i++) {
    while (v[id].first < i && id < vs) {
      num += v[id].first;
      id++;
    }
    int curnum = (num + (vs - id) * i);
    curnum -= curnum % i;
    if (curnum / i >= i) {
      if (best < curnum) {
        best = curnum;
        besx = i;
      }
    }
  }
  int besy = best / besx;
  best = besx * besy;
  printf("%d\n%d %d\n", best, besx, besy);
  vector<int> order;
  for (int i = vs - 1; i >= 0; i--) {
    int num = min(besx, v[i].first);
    while (num--) order.push_back(v[i].second);
  }
  while (order.size() > best) order.pop_back();
  int curx = 0, cury = 0;
  int grid[besx][besy];
  memset(grid, -1, sizeof(grid));
  for (int i = 0; i < best; i++) {
    grid[curx][cury] = order[i];
    curx++;
    curx %= besx;
    cury++;
    cury %= besy;
    if (grid[curx][cury] != -1) curx++;
  }
  for (int i = 0; i < besx; i++) {
    for (int j = 0; j < besy; j++) {
      printf("%d ", grid[i][j]);
    }
    printf("\n");
  }
}
