#include <bits/stdc++.h>
using namespace std;
istream& inp = cin;
int main() {
  int n;
  inp >> n;
  vector<int> a;
  for (int i = 0; i < n; ++i) {
    int x;
    inp >> x;
    a.push_back(x);
  }
  map<int, int> buckets;
  for (int x : a) {
    auto it = buckets.find(x);
    if (it == buckets.end())
      buckets[x] = 1;
    else
      ++it->second;
  }
  vector<pair<int, int>> s;
  for (auto& p : buckets) s.push_back(p);
  auto cmp = [&](const pair<int, int>& a, const pair<int, int>& b) {
    return a.second < b.second;
  };
  sort(s.begin(), s.end(), cmp);
  vector<int> pre{0};
  int sum = 0;
  for (auto p : s) {
    sum += p.second;
    pre.push_back(sum);
  }
  int bestq = 0;
  int bestp;
  int bestx = 0;
  for (int q = 1; q <= buckets.size(); ++q) {
    const int p = min(q, n / q);
    auto it = lower_bound(s.begin(), s.end(), make_pair(-1, p), cmp);
    int pos = it - s.begin();
    int p1 = ((s.size() - pos >= q)
                  ? p
                  : min(p, pre.at(pos) / (q - (int(s.size()) - pos))));
    int x = p1 * q;
    if (x > bestx) {
      bestx = x;
      bestq = q;
      bestp = p1;
    }
  }
  cout << bestx << "\n";
  int p = bestp;
  int q = bestq;
  cout << p << " " << q << "\n";
  vector<int> v;
  for (auto pair : s)
    for (int i = 0; i < min(pair.second, p); ++i) v.push_back(pair.first);
  auto it = v.rbegin();
  vector<vector<int>> out(p, vector<int>(q, -1));
  for (int x = 0; x < q; ++x)
    for (int y = 0; y < p; ++y) out.at(y).at((x + y) % q) = *(it++);
  for (auto& row : out) {
    for (int x : row) cout << x << " ";
    cout << "\n";
  }
  for (auto& row : out) {
    set<int> s;
    for (int x : row) {
      assert(x != -1);
      assert(s.find(x) == s.end());
      s.insert(x);
    }
  }
  for (int x = 0; x < q; ++x) {
    set<int> s;
    for (int y = 0; y < p; ++y) {
      int z = out.at(y).at(x);
      assert(s.find(z) == s.end());
      s.insert(z);
    }
  }
  return 0;
}
