#include <bits/stdc++.h>
using namespace std;
long long gcd(long long a, long long b) { return b == 0 ? a : gcd(b, a % b); }
pair<long long, long long> partition_numbers(const vector<long long> &v,
                                             bool nonempty = true,
                                             int parity = -1) {
  int n = ((int)(v).size()), na = n / 2, nb = n - na;
  vector<pair<long long, long long>> a(1, make_pair(0LL, 0LL));
  for (int i = (0); i < (na); ++i) {
    vector<pair<long long, long long>> aa(2 * ((int)(a).size()));
    int x = 0, y = 0;
    while (x < ((int)(a).size()) || y < ((int)(a).size()))
      if (x < ((int)(a).size()) &&
          (y >= ((int)(a).size()) || a[x].first - v[i] <= a[y].first + v[i]))
        aa[x + y] = make_pair(a[x].first - v[i], a[x].second), ++x;
      else
        aa[x + y] = make_pair(a[y].first + v[i], a[y].second | (1LL << i)), ++y;
    swap(a, aa);
  }
  vector<pair<long long, long long>> b(1, make_pair(0LL, 0LL));
  for (int i = (0); i < (nb); ++i) {
    vector<pair<long long, long long>> bb(2 * ((int)(b).size()));
    int j = na + i;
    int x = 0, y = 0;
    while (x < ((int)(b).size()) || y < ((int)(b).size()))
      if (x < ((int)(b).size()) &&
          (y >= ((int)(b).size()) || b[x].first - v[j] <= b[y].first + v[j]))
        bb[x + y] = make_pair(b[x].first - v[j], b[x].second), ++x;
      else
        bb[x + y] = make_pair(b[y].first + v[j], b[y].second | (1LL << j)), ++y;
    swap(b, bb);
  }
  reverse(b.begin(), b.end());
  pair<long long, long long> ret = make_pair(LLONG_MAX, 0);
  auto upd = [&](int ai, int bi) {
    pair<long long, long long> cur =
        make_pair(abs(a[ai].first + b[bi].first), a[ai].second | b[bi].second);
    ret = min(ret, cur);
  };
  for (int apar = (0); apar < (2); ++apar)
    for (int bpar = (0); bpar < (2); ++bpar) {
      if (parity != -1 && (apar + bpar) % 2 != parity) continue;
      int ai = 0, bi = 0;
      while (ai < ((int)(a).size()) && bi < ((int)(b).size())) {
        if ((a[ai].first % 2 == 0) != (apar == 0)) {
          ++ai;
          continue;
        }
        if ((b[bi].first % 2 == 0) != (bpar == 0)) {
          ++bi;
          continue;
        }
        if (nonempty &&
            (a[ai].second == 0 || a[ai].second == (1LL << na) - 1)) {
          ++ai;
          continue;
        }
        if (nonempty &&
            (b[bi].second == 0 || b[bi].second == (1LL << n) - (1LL << na))) {
          ++bi;
          continue;
        }
        upd(ai, bi);
        if (a[ai].first + b[bi].first <= 0)
          ++ai;
        else
          ++bi;
      }
    }
  if (nonempty && na >= 1 && nb >= 1) {
    for (int ai = (0); ai < (((int)(a).size())); ++ai) {
      if (a[ai].second == 0) {
        for (int k = (0); k < (((int)(b).size())); ++k)
          if (b[k].second != 0 &&
              (parity == -1 ||
               ((a[ai].first + b[k].first) % 2 == 0) == (parity == 0)))
            upd(ai, k);
      }
      if (a[ai].second == (1LL << na) - 1) {
        for (int k = (0); k < (((int)(b).size())); ++k)
          if (b[k].second != (1LL << n) - (1LL << na) &&
              (parity == -1 ||
               ((a[ai].first + b[k].first) % 2 == 0) == (parity == 0)))
            upd(ai, k);
      }
    }
    for (int bi = (0); bi < (((int)(b).size())); ++bi) {
      if (b[bi].second == 0) {
        for (int k = (0); k < (((int)(a).size())); ++k)
          if (a[k].second != 0 &&
              (parity == -1 ||
               ((a[k].first + b[bi].first) % 2 == 0) == (parity == 0)))
            upd(k, bi);
      }
      if (b[bi].second == (1LL << n) - (1LL << na)) {
        for (int k = (0); k < (((int)(a).size())); ++k)
          if (a[k].second != (1LL << na) - 1 &&
              (parity == -1 ||
               ((a[k].first + b[bi].first) % 2 == 0) == (parity == 0)))
            upd(k, bi);
      }
    }
  }
  return ret;
}
struct SubsetConvolution1 {
  int n;
  vector<int> cnt;
  SubsetConvolution1(int _n) {
    n = _n;
    cnt = vector<int>(1 << n);
    cnt[0] = 0;
    for (int mask = (1); mask < (1 << n); ++mask)
      cnt[mask] = cnt[mask >> 1] + (mask & 1);
  }
  struct Function {
    vector<int> func;
    vector<vector<int>> rankedtrans;
  };
  void transform(vector<int> &v) {
    for (int step = 1 << (n - 1); step >= 1; step >>= 1)
      for (int base = 0; base < (1 << n); base += step << 1)
        for (int offset = (0); offset < (step); ++offset)
          v[base + step + offset] += v[base + offset];
  }
  void invtransform(vector<int> &v) {
    for (int step = 1 << (n - 1); step >= 1; step >>= 1)
      for (int base = 0; base < (1 << n); base += step << 1)
        for (int offset = (0); offset < (step); ++offset)
          v[base + step + offset] -= v[base + offset];
  }
  void ensureranked(Function &f) {
    if (((int)(f.rankedtrans).size()) > 0)
      return;
    else
      assert(((int)(f.func).size()) > 0);
    f.rankedtrans = vector<vector<int>>(n + 1, vector<int>(1 << n, 0));
    for (int mask = (0); mask < (1 << n); ++mask)
      f.rankedtrans[cnt[mask]][mask] += f.func[mask];
    for (int k = (0); k <= (n); ++k) transform(f.rankedtrans[k]);
  }
  Function convert(const vector<bool> &can) {
    Function ret;
    ret.func = vector<int>(1 << n);
    for (int mask = (0); mask < (1 << n); ++mask)
      ret.func[mask] = can[mask] ? 1 : 0;
    return ret;
  }
  Function mult(Function &f, Function &g) {
    ensureranked(f);
    ensureranked(g);
    Function ret;
    ret.rankedtrans = vector<vector<int>>(n + 1, vector<int>(1 << n, 0));
    for (int k = (0); k <= (n); ++k)
      for (int j = (0); j <= (k); ++j)
        for (int mask = (0); mask < (1 << n); ++mask)
          ret.rankedtrans[k][mask] +=
              f.rankedtrans[j][mask] * g.rankedtrans[k - j][mask];
    return ret;
  }
  bool any(const Function &f) {
    if (((int)(f.func).size()) > 0) {
      for (int mask = (0); mask < (1 << n); ++mask)
        if (f.func[mask] != 0) return true;
      return false;
    }
    if (((int)(f.rankedtrans).size()) > 0) {
      for (int k = (0); k <= (n); ++k) {
        vector<int> rankedfunc = f.rankedtrans[k];
        invtransform(rankedfunc);
        for (int mask = (0); mask < (1 << n); ++mask)
          if (cnt[mask] == k && rankedfunc[mask] != 0) return true;
      }
      return false;
    }
    assert(false);
    return false;
  }
  int maxDisjointSets(vector<bool> can) {
    vector<Function> p(1, convert(can));
    while (true) {
      int idx = ((int)(p).size()) - 1;
      if (!any(p[idx])) break;
      Function tmp = p[idx];
      p.emplace_back(mult(tmp, tmp));
    }
    p.pop_back();
    if (((int)(p).size()) == 0) return 0;
    int myidx = ((int)(p).size()) - 1, ret = 1 << myidx;
    for (int i = ((int)(p).size()) - 2; i >= 0; --i) {
      Function cur = mult(p[myidx], p[i]);
      if (!any(cur)) continue;
      swap(p[myidx], cur);
      ret += 1 << i;
    }
    return ret;
  }
};
struct SubsetConvolution {
  int n;
  vector<int> cnt;
  SubsetConvolution(int _n) {
    n = _n;
    cnt = vector<int>(1 << n);
    cnt[0] = 0;
    for (int mask = (1); mask < (1 << n); ++mask)
      cnt[mask] = cnt[mask >> 1] + (mask & 1);
  }
  void transform(vector<int> &v) {
    for (int step = 1 << (n - 1); step >= 1; step >>= 1)
      for (int base = 0; base < (1 << n); base += step << 1)
        for (int offset = (0); offset < (step); ++offset)
          v[base + step + offset] += v[base + offset];
  }
  void invtransform(vector<int> &v) {
    for (int step = 1 << (n - 1); step >= 1; step >>= 1)
      for (int base = 0; base < (1 << n); base += step << 1)
        for (int offset = (0); offset < (step); ++offset)
          v[base + step + offset] -= v[base + offset];
  }
  int maxDisjointSets(vector<bool> can) {
    vector<vector<int>> one(n + 1, vector<int>(1 << n, 0));
    int mnone = INT_MAX;
    for (int mask = (0); mask < (1 << n); ++mask)
      if (can[mask]) ++one[cnt[mask]][mask], mnone = min(mnone, cnt[mask]);
    assert(mnone >= 1);
    if (mnone == INT_MAX) return 0;
    for (int k = (mnone); k <= (n); ++k) transform(one[k]);
    vector<vector<int>> cur = one;
    int mncur = mnone, ret = 1;
    vector<vector<int>> nxt(n + 1, vector<int>(1 << n, 0));
    while (true) {
      for (int k = (mncur + mnone); k <= (n); ++k)
        for (int mask = (0); mask < (1 << n); ++mask) nxt[k][mask] = 0;
      for (int k = (mncur + mnone); k <= (n); ++k)
        for (int j = (mncur); j <= (k - mnone); ++j)
          for (int mask = (0); mask < (1 << n); ++mask)
            nxt[k][mask] += cur[j][mask] * one[k - j][mask];
      int mnnxt = INT_MAX;
      for (int k = (mncur + mnone); k <= (n); ++k) {
        vector<int> z = nxt[k];
        invtransform(z);
        for (int mask = (0); mask < (1 << n); ++mask)
          if (cnt[mask] == k && z[mask] != 0) {
            mnnxt = k;
            break;
          }
        if (mnnxt != INT_MAX) break;
      }
      if (mnnxt == INT_MAX) return ret;
      swap(cur, nxt);
      mncur = mnnxt;
      ++ret;
    }
  }
};
const int MAXN = 20;
int n;
long long a[MAXN];
long long b[MAXN];
int nb;
int solve() {
  nb = 0;
  for (int i = (0); i < (n); ++i)
    if (a[i] != 0) b[nb++] = a[i];
  vector<bool> one(1 << nb);
  for (int mask = (0); mask < (1 << nb); ++mask) {
    vector<long long> v;
    for (int i = (0); i < (nb); ++i)
      if (mask & (1 << i)) v.push_back(b[i]);
    long long mindiff =
        partition_numbers(v, true, ((int)(v).size()) % 2 == 0 ? 1 : 0).first;
    one[mask] = ((int)(v).size()) == 1 && v[0] == 0 ||
                ((int)(v).size()) >= 2 && mindiff <= ((int)(v).size()) - 1;
  }
  SubsetConvolution sc(nb);
  int save = sc.maxDisjointSets(one);
  return nb - save;
}
void run() {
  scanf("%d", &n);
  for (int i = (0); i < (n); ++i) scanf("%lld", &a[i]);
  printf("%d\n", solve());
}
int main() {
  run();
  return 0;
}
