#include <bits/stdc++.h>
using namespace std;
template <typename... As>
struct tpl : public std::tuple<As...> {
  using std::tuple<As...>::tuple;
  tpl(std::tuple<As...> const& b) { std::tuple<As...>::operator=(b); }
  template <typename T = tuple<As...>>
  typename tuple_element<0, T>::type const& x() const {
    return get<0>(*this);
  }
  template <typename T = tuple<As...>>
  typename tuple_element<0, T>::type& x() {
    return get<0>(*this);
  }
  template <typename T = tuple<As...>>
  typename tuple_element<1, T>::type const& y() const {
    return get<1>(*this);
  }
  template <typename T = tuple<As...>>
  typename tuple_element<1, T>::type& y() {
    return get<1>(*this);
  }
  template <typename T = tuple<As...>>
  typename tuple_element<2, T>::type const& z() const {
    return get<2>(*this);
  }
  template <typename T = tuple<As...>>
  typename tuple_element<2, T>::type& z() {
    return get<2>(*this);
  }
  template <typename T = tuple<As...>>
  typename tuple_element<3, T>::type const& w() const {
    return get<3>(*this);
  }
  template <typename T = tuple<As...>>
  typename tuple_element<3, T>::type& w() {
    return get<3>(*this);
  }
};
using lli = long long int;
using llu = long long unsigned;
using pii = tpl<lli, lli>;
using piii = tpl<lli, lli, lli>;
using piiii = tpl<lli, lli, lli, lli>;
using vi = vector<lli>;
using vii = vector<pii>;
using viii = vector<piii>;
using vvi = vector<vi>;
using vvii = vector<vii>;
using vviii = vector<viii>;
template <class T>
using min_queue = priority_queue<T, vector<T>, greater<T>>;
template <class T>
using max_queue = priority_queue<T>;
template <size_t... I>
struct my_index_sequence {
  using type = my_index_sequence;
  static constexpr array<size_t, sizeof...(I)> value = {{I...}};
};
namespace my_index_sequence_detail {
template <typename I, typename J>
struct concat;
template <size_t... I, size_t... J>
struct concat<my_index_sequence<I...>, my_index_sequence<J...>>
    : my_index_sequence<I..., (sizeof...(I) + J)...> {};
template <size_t N>
struct make_index_sequence
    : concat<typename make_index_sequence<N / 2>::type,
             typename make_index_sequence<N - N / 2>::type>::type {};
template <>
struct make_index_sequence<0> : my_index_sequence<> {};
template <>
struct make_index_sequence<1> : my_index_sequence<0> {};
}  // namespace my_index_sequence_detail
template <class... A>
using my_index_sequence_for =
    typename my_index_sequence_detail::make_index_sequence<sizeof...(A)>::type;
template <class T, size_t... I>
void print_tuple(ostream& s, T const& a, my_index_sequence<I...>) {
  using swallow = int[];
  (void)swallow{0, (void(s << (I == 0 ? "" : ", ") << get<I>(a)), 0)...};
}
template <class T>
ostream& print_collection(ostream& s, T const& a);
template <class... A>
ostream& operator<<(ostream& s, tpl<A...> const& a);
template <class... A>
ostream& operator<<(ostream& s, tuple<A...> const& a);
template <class A, class B>
ostream& operator<<(ostream& s, pair<A, B> const& a);
template <class T, size_t I>
ostream& operator<<(ostream& s, array<T, I> const& a) {
  return print_collection(s, a);
}
template <class T>
ostream& operator<<(ostream& s, vector<T> const& a) {
  return print_collection(s, a);
}
template <class T, class U>
ostream& operator<<(ostream& s, multimap<T, U> const& a) {
  return print_collection(s, a);
}
template <class T>
ostream& operator<<(ostream& s, multiset<T> const& a) {
  return print_collection(s, a);
}
template <class T, class U>
ostream& operator<<(ostream& s, map<T, U> const& a) {
  return print_collection(s, a);
}
template <class T>
ostream& operator<<(ostream& s, set<T> const& a) {
  return print_collection(s, a);
}
template <class T>
ostream& print_collection(ostream& s, T const& a) {
  s << '[';
  for (auto it = begin(a); it != end(a); ++it) {
    s << *it;
    if (it != prev(end(a))) s << " ";
  }
  return s << ']';
}
template <class... A>
ostream& operator<<(ostream& s, tpl<A...> const& a) {
  s << '(';
  print_tuple(s, a, my_index_sequence_for<A...>{});
  return s << ')';
}
template <class... A>
ostream& operator<<(ostream& s, tuple<A...> const& a) {
  s << '(';
  print_tuple(s, a, my_index_sequence_for<A...>{});
  return s << ')';
}
template <class A, class B>
ostream& operator<<(ostream& s, pair<A, B> const& a) {
  return s << "(" << get<0>(a) << ", " << get<1>(a) << ")";
}
namespace std {
namespace {
template <class T>
inline void hash_combine(size_t& seed, T const& v) {
  seed ^= hash<T>()(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
template <class Tuple, size_t Index = tuple_size<Tuple>::value - 1>
struct HashValueImpl {
  static void apply(size_t& seed, Tuple const& tuple) {
    HashValueImpl<Tuple, Index - 1>::apply(seed, tuple);
    hash_combine(seed, get<Index>(tuple));
  }
};
template <class Tuple>
struct HashValueImpl<Tuple, 0> {
  static void apply(size_t& seed, Tuple const& tuple) {
    hash_combine(seed, get<0>(tuple));
  }
};
}  // namespace
template <typename... TT>
struct hash<tuple<TT...>> {
  size_t operator()(tuple<TT...> const& tt) const {
    size_t seed = 0;
    HashValueImpl<tuple<TT...>>::apply(seed, tt);
    return seed;
  }
};
template <typename... TT>
struct hash<tpl<TT...>> {
  size_t operator()(tpl<TT...> const& tt) const {
    size_t seed = 0;
    HashValueImpl<tuple<TT...>>::apply(seed, tt);
    return seed;
  }
};
}  // namespace std
struct MaxFlow {
  const lli infinity = numeric_limits<lli>::max();
  struct edge {
    edge(lli to_, lli c_) : to(to_), c(c_), f(0) {}
    lli to, c, f;
    edge* rev;
  };
  vector<vector<edge*>> G;
  MaxFlow(lli n = 0) : G(n) {}
  lli addNode() {
    G.emplace_back();
    return G.size() - 1;
  }
  edge* addEdge(lli a, lli b, lli c) {
    edge* e1 = new edge(b, c);
    edge* e2 = new edge(a, 0);
    e1->rev = e2;
    e2->rev = e1;
    G[a].push_back(e1);
    G[b].push_back(e2);
    return e1;
  }
  vector<edge*> get_minimum_cut(lli S) {
    int n = G.size();
    vi E(n);
    function<void(int)> dfs = [&](int i) {
      if (E[i]) return;
      E[i] = 1;
      for (edge* e : G[i])
        if (e->f < e->c) dfs(e->to);
    };
    dfs(S);
    vector<edge*> R;
    for (lli i = 0; i < (lli)(n); ++i)
      if (E[i])
        for (edge* e : G[i])
          if (!E[e->to]) R.push_back(e);
    return R;
  }
  lli flow(lli S, lli T) {
    lli N = G.size();
    lli f = 0;
    vi D, W;
    while (1) {
      D.assign(N, -1);
      queue<lli> Q;
      Q.push(S);
      D[S] = 0;
      while (!Q.empty()) {
        lli i = Q.front();
        Q.pop();
        if (i == T) break;
        for (edge* e : G[i])
          if (e->c > e->f && D[e->to] == -1) {
            D[e->to] = D[i] + 1;
            Q.push(e->to);
          }
      }
      if (D[T] == -1) return f;
      W.assign(N, 0);
      function<lli(lli, lli)> dfs = [&](lli i, lli f) {
        if (i == T) return f;
        lli cf = 0;
        for (; W[i] < (lli)G[i].size(); W[i]++) {
          edge* e = G[i][W[i]];
          if (e->c > e->f && D[e->to] == D[i] + 1) {
            lli df = dfs(e->to, min(f, e->c - e->f));
            if (df > 0) {
              cf += df;
              f -= df;
              e->f += df;
              e->rev->f -= df;
            }
          }
        }
        return cf;
      };
      while (lli df = dfs(S, infinity)) f += df;
    }
  }
};
MaxFlow::edge* VV[100][100];
int ans[100][100];
void print(vi R) {
  int n = R.size();
  MaxFlow G(2 + n * n + 1 + n);
  int S = 0, T = 1;
  for (lli i = 0; i < (lli)(n); ++i) {
    G.addEdge(2 + i, T, R[i]);
  }
  int cur = 0;
  for (lli i = 0; i < (lli)(n); ++i)
    for (lli j = (i + 1); j <= (lli)(n - 1); ++j) {
      G.addEdge(S, 2 + n + cur, 1);
      VV[i][j] = G.addEdge(2 + n + cur, 2 + i, 1);
      G.addEdge(2 + n + cur, 2 + j, 1);
      cur += 1;
    }
  int f = G.flow(S, T);
  assert(f == accumulate(begin(R), end(R), 0));
  for (lli i = 0; i < (lli)(n); ++i)
    for (lli j = (i + 1); j <= (lli)(n - 1); ++j) {
      ans[i][j] = (VV[i][j]->f) ? 1 : 0;
      ans[j][i] = 1 - ans[i][j];
    }
  cout << n << endl;
  for (lli i = 0; i < (lli)(n); ++i) {
    ans[i][i] = 0;
    for (lli j = 0; j < (lli)(n); ++j) cout << ans[i][j];
    cout << '\n';
  }
  cout << flush;
}
bool dp[42][101][5000];
int last[42][101][5000];
int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  int n;
  cin >> n;
  vi A(n);
  for (lli i = 0; i < (lli)(n); ++i) cin >> A[i];
  sort(begin(A), end(A));
  dp[0][0][0] = 1;
  last[0][0][0] = -1;
  for (lli i = 0; i < (lli)(n); ++i)
    for (lli j = 0; j < (lli)(100); ++j)
      for (lli k = 0; k < (lli)(5000); ++k)
        if (dp[i][j][k]) {
          if (k + A[i] >= (j * (j + 1)) / 2 && k + A[i] < 5000) {
            dp[i][j + 1][k + A[i]] = 1;
            last[i][j + 1][k + A[i]] = i;
          }
          if (i + 1 < n && j != 0) {
            if (k + A[i + 1] >= (j * (j + 1)) / 2 && k + A[i + 1] < 5000) {
              dp[i + 1][j + 1][k + A[i + 1]] = 1;
              last[i + 1][j + 1][k + A[i + 1]] = i;
            }
          }
        }
  for (lli j = (1); j <= (lli)(100); ++j)
    if (dp[n - 1][j][(j * (j - 1)) / 2]) {
      vi R;
      int l = n - 1;
      int jj = j;
      int kk = (j * (j - 1)) / 2;
      while (jj) {
        assert(dp[l][jj][kk]);
        int x = A[l];
        R.push_back(x);
        l = last[l][jj][kk];
        jj -= 1;
        kk -= x;
      }
      print(R);
      return 0;
    }
  cout << "=(" << endl;
  return 0;
}
