Problem p03201 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <bits/stdc++.h>
#define fr(i, n) for (int i = 0; i < (n); ++i)
#define foor(i, a, b) for (int i = (a); i <= (b); ++i)
#define rf(i, n) for (int i = (n); i--;)
#define roof(i, b, a) for (int i = (b); i >= (a); --i)
#define elsif else if
#define all(x) x.begin(), x.end()
#define Sort(x) sort(all(x))
#define Reverse(x) reverse(all(x))
#define PQ priority_queue
#define NP(x) next_permutation(all(x))
#define M_PI 3.14159265358979323846
using namespace std;
typedef vector<bool> vb;
typedef vector<vb> vvb;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef unsigned long long ull;
typedef vector<ull> vu;
typedef vector<vu> vvu;
typedef double dbl;
typedef vector<dbl> vd;
typedef vector<vd> vvd;
typedef string str;
typedef vector<str> vs;
typedef vector<vs> vvs;
typedef pair<int, int> pii;
typedef vector<pii> vpii;
typedef map<int, int> mii;
typedef pair<ll, ll> pll;
typedef vector<pll> vpll;
typedef map<ll, ll> mll;
typedef pair<dbl, dbl> pdd;
typedef vector<pdd> vpdd;
typedef map<dbl, dbl> mdd;
typedef pair<str, str> pss;
typedef vector<pss> vpss;
typedef map<str, str> mss;
typedef pair<int, ll> pil;
typedef vector<pil> vpil;
typedef map<int, ll> mil;
typedef pair<ll, int> pli;
typedef vector<pli> vpli;
typedef map<ll, int> mli;
typedef pair<dbl, int> pdi;
typedef vector<pdi> vpdi;
typedef map<dbl, int> mdi;
template <typename T> vector<T> &operator<<(vector<T> &v, const T t) {
  v.push_back(t);
  return v;
}
template <typename T> multiset<T> &operator<<(multiset<T> &m, const T t) {
  m.insert(t);
  return m;
}
template <typename T> set<T> &operator<<(set<T> &s, const T t) {
  s.insert(t);
  return s;
}
template <typename T> stack<T> &operator<<(stack<T> &s, const T t) {
  s.push(t);
  return s;
}
template <typename T> queue<T> &operator<<(queue<T> &q, const T t) {
  q.push(t);
  return q;
}
template <typename T, typename U>
PQ<T, vector<T>, U> &operator<<(PQ<T, vector<T>, U> &q, const T t) {
  q.push(t);
  return q;
}
template <typename T, typename U>
istream &operator>>(istream &s, pair<T, U> &p) {
  return s >> p.first >> p.second;
}
template <typename T> istream &operator>>(istream &s, vector<T> &v) {
  fr(i, v.size()) { s >> v[i]; }
  return s;
}
template <typename T, typename U>
ostream &operator<<(ostream &s, const pair<T, U> p) {
  return s << p.first << " " << p.second;
}
// template<typename T>ostream&operator<<(ostream&s,const vector<T>v){for(auto
// a:v){s<<a<<endl;}return s;}
template <typename T> ostream &operator<<(ostream &s, const vector<T> v) {
  fr(i, v.size()) { i ? s << " " << v[i] : s << v[i]; }
  return s;
}
template <typename T, typename U>
pair<T, U> operator+(pair<T, U> a, pair<T, U> b) {
  return {a.first + b.first, a.second + b.second};
}
template <typename T, typename U>
pair<T, U> operator-(pair<T, U> a, pair<T, U> b) {
  return {a.first - b.first, a.second - b.second};
}
void print(void) { cout << endl; }
template <typename T> void print(T t) { cout << t << endl; }
template <typename T, typename... U> void print(T &&t, U &&...u) {
  cout << t << " ";
  print(forward<U>(u)...);
}
bool YN(bool b) {
  print(b ? "YES" : "NO");
  return b;
}
bool PI(bool b) {
  print(b ? "POSSIBLE" : "IMPOSSIBLE");
  return b;
}
bool Yn(bool b) {
  print(b ? "Yes" : "No");
  return b;
}
bool Pi(bool b) {
  print(b ? "Possible" : "Impossible");
  return b;
}
bool yn(bool b) {
  print(b ? "yes" : "no");
  return b;
}
bool pi(bool b) {
  print(b ? "possible" : "impossible");
  return b;
}
const int MD = 1e9 + 7;
template <typename T> str to_string(const T &n) {
  ostringstream s;
  s << n;
  return s.str();
}
template <typename T, typename U>
vector<pair<T, U>> dijkstra(const vector<vector<pair<T, U>>> E, const U s,
                            const T inf) {
  using P = pair<T, U>;
  vector<P> d;
  fr(i, E.size()) { d << P{inf, i}; }
  PQ<P, vector<P>, greater<P>> pq;
  pq << (d[s] = P{0, s});
  while (pq.size()) {
    P a = pq.top();
    pq.pop();
    U v = a.second;
    if (d[v].first >= a.first) {
      for (P e : E[v]) {
        if (d[v].first + e.first < d[e.second].first) {
          d[e.second] = P{d[v].first + e.first, v};
          pq << P{d[v].first + e.first, e.second};
        }
      }
    }
  }
  return d;
}
template <typename T, typename U>
map<U, pair<T, U>> dijkstra(map<U, vector<pair<T, U>>> E, const U s,
                            const T inf) {
  using P = pair<T, U>;
  map<U, P> d;
  for (pair<U, vector<P>> e : E) {
    d[e.first] = P{inf, e.first};
  }
  PQ<P, vector<P>, greater<P>> pq;
  pq << (d[s] = P{0, s});
  while (pq.size()) {
    P a = pq.top();
    pq.pop();
    U v = a.second;
    if (d[v].first >= a.first) {
      for (P e : E[v]) {
        if (d[v].first + e.first < d[e.second].first) {
          d[e.second] = P{d[v].first + e.first, v};
          pq << P{d[v].first + e.first, e.second};
        }
      }
    }
  }
  return d;
}
template <typename T> T distsq(pair<T, T> a, pair<T, T> b) {
  return (a.first - b.first) * (a.first - b.first) +
         (a.second - b.second) * (a.second - b.second);
}
template <typename T> T max(const vector<T> a) {
  T m = a[0];
  for (T e : a) {
    m = max(m, e);
  }
  return m;
}
template <typename T> T min(const vector<T> a) {
  T m = a[0];
  for (T e : a) {
    m = min(m, e);
  }
  return m;
}
template <typename T> T gcd(const T a, const T b) {
  return a ? gcd(b % a, a) : b;
}
template <typename T> T gcd(const vector<T> a) {
  T g = a[0];
  for (T e : a) {
    g = gcd(g, e);
  }
  return g;
}
template <typename T> vector<T> LIS(const vector<T> A) {
  vi B;
  for (T a : A) {
    auto it = lower_bound(all(B), a);
    if (it == B.end()) {
      B << a;
    } else {
      *it = a;
    }
  }
  return B;
}
template <typename T> vector<pair<T, T>> ConvexHull(vector<pair<T, T>> V) {
  if (V.size() <= 3) {
    return V;
  }
  Sort(V);
  rf(i, V.size() - 1) V << V[i];
  vector<pair<T, T>> r;
  for (pair<T, T> p : V) {
    int s = r.size();
    while (s >= 2 &&
           (p.second - r[s - 1].second) * (p.first - r[s - 2].first) <
               (p.second - r[s - 2].second) * (p.first - r[s - 1].first)) {
      r.pop_back();
      --s;
    }
    r << p;
  }
  r.pop_back();
  return r;
}
class UnionFind {
  vi p, r, s;

public:
  UnionFind(int N) {
    p = r = vi(N);
    s = vi(N, 1);
    fr(i, N) { p[i] = i; }
  }
  int find(int i) { return p[i] = p[i] == i ? i : find(p[i]); }
  void unite(int a, int b) {
    if (r[a = find(a)] > r[b = find(b)]) {
      swap(a, b);
    }
    s[b] += s[a];
    r[p[a] = b] += r[a] == r[b];
  }
  bool same(int a, int b) { return find(a) == find(b); }
  int size(int x) { return s[find(x)]; }
};
ll strmod(const str &s, const int m) {
  ll x = 0;
  fr(i, s.size()) { x = (x * 10 + s[i] - 48) % m; }
  return x;
}
vvl mul(const vvl &A, const vvl &B, const int m) {
  vvl C;
  fr(y, A.size()) { C << vl(B[y].size()); }
  fr(y, C.size()) {
    fr(x, C[y].size()) {
      fr(i, A[0].size()) { (C[y][x] += A[y][i] * B[i][x]) %= m; }
    }
  }
  return C;
}
vvl pow(const vvl &A, const ll n, const int m) {
  vvl B;
  fr(y, A.size()) { B << vl(A.size()); }
  if (n == 0) {
    fr(i, B.size()) { B[i][i] = 1; }
  }
  elsif(n % 2) { B = mul(A, pow(A, n - 1, m), m); }
  else {
    vvl C = pow(A, n / 2, m);
    B = mul(C, C, m);
  }
  return B;
}
ll pow(const ll a, const ll n, const int m) {
  ll t;
  return n ? (n & 1 ? a >= 0 ? a % m : (m - (-a % m)) % m : 1) *
                 (t = pow(a, n >> 1, m), t * t % m) % m
           : !!a;
}
ll inv(const ll x, const int p) { return pow(x, p - 2, p); }
ll inv(const ll x) { return inv(x, MD); }
vpll fact(const int n, const int p) {
  vpll v(n + 1);
  v[0].first = 1;
  foor(i, 1, n) { v[i].first = v[i - 1].first * i % p; }
  v[n].second = inv(v[n].first, p);
  roof(i, n, 1) { v[i - 1].second = v[i].second * i % p; }
  return v;
}
class Combination {
  const vpll f;
  const int M;

public:
  Combination(int n, int m) : f(fact(n, m)), M(m) {}
  Combination(int n) : Combination(n, MD) {}
  ll P(int n, int k) {
    return n < 0 || k < 0 || n < k ? 0ll : f[n].first * f[n - k].second % M;
  }
  ll C(int n, int k) { return P(n, k) * f[k].second % M; }
  ll H(int n, int k) { return n == 0 && k == 0 ? 1ll : C(n + k - 1, k); }
};
ll C2(const int n) { return (ll)n * ~-n / 2; }
ll sum(const vi a) {
  ll s = 0;
  for (int e : a) {
    s += e;
  }
  return s;
}
ll sum(const vl a) {
  ll s = 0;
  for (ll e : a) {
    s += e;
  }
  return s;
}
template <typename T> int MSB(T N) {
  int r = -1;
  for (; N > 0; N /= 2) {
    ++r;
  }
  return r;
}
template <typename T> class SegmentTree {
  vector<T> S;
  T (*const op)(T a, T b);
  const T zero;
  const int B;

public:
  SegmentTree(int N, T (*f)(T a, T b), const T zero)
      : S(1 << MSB(N - 1) + 2, zero), op(f), zero(zero),
        B(1 << MSB(N - 1) + 1) {}
  SegmentTree(vector<T> v, T (*f)(T a, T b), const T zero)
      : SegmentTree(v.size(), f, zero) {
    fr(i, v) { S[S.size() / 2 + i] = v[i]; }
    roof(i, S.size() / 2 - 1, 1) { S[i] = op(S[i * 2], S[i * 2 + 1]); }
  }
  T calc(int l, int r) {
    l += B;
    r += B;
    if (l > r) {
      return zero;
    }
    if (l == r) {
      return S[l];
    }
    T L = S[l], R = S[r];
    for (; l / 2 < r / 2; l /= 2, r /= 2) {
      if (l % 2 == 0) {
        L = op(L, S[l + 1]);
      }
      if (r % 2 == 1) {
        R = op(S[r - 1], R);
      }
    }
    return op(L, R);
  }
  void replace(int i, T x) {
    for (S[i += B] = x; i != 1; i /= 2) {
      if (i % 2) {
        S[i / 2] = op(S[i - 1], S[i]);
      } else {
        S[i / 2] = op(S[i], S[i + 1]);
      }
    }
  }
  void add(int i, T x) { replace(i, op(S[B + i], x)); }
  T top() { return S[1]; }
};
ll BITsum(vl &B, int i) {
  ll z = 0;
  while (i > 0) {
    z += B[i];
    i -= i & -i;
  }
  return z;
}
void BITadd(vl &B, int i, ll x) {
  while (i < B.size()) {
    B[i] += x;
    i += i & -i;
  }
}
ll fib(const ll n, const int m) {
  ll a, b, c, d, A, B, C, D;
  a = 1;
  b = 0;
  c = 0;
  d = 1;
  rf(i, 63) {
    A = a * a + b * c;
    B = a * b + b * d;
    C = c * a + d * c;
    D = c * b + d * d;
    if (n >> i & 1) {
      a = A;
      b = B;
      c = C;
      d = D;
      A = a + b;
      B = a;
      C = c + d;
      D = c;
    }
    a = A % m;
    b = B % m;
    c = C % m;
    d = D % m;
  }
  return b;
}
vi primes(int n) {
  vb b(n + 1);
  vi p;
  foor(i, 2, n) {
    if (!b[i]) {
      p << i;
      for (int j = 2 * i; j <= n; j += i) {
        b[j] = true;
      }
    }
  }
  return p;
}
vb isprime(const int n) {
  vb v(n + 1, true);
  v[0] = v[1] = false;
  foor(i, 2, n) {
    if (v[i]) {
      for (int j = 2 * i; j <= n; j += i) {
        v[j] = false;
      }
    }
  }
  return v;
}

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  int N;
  cin >> N;
  vi A(N);
  cin >> A;
  Sort(A);
  Reverse(A);
  int z = 0;
  mii m;
  fr(i, N) { ++m[A[i]]; }
  fr(i, N) {
    if (m[A[i]]) {
      rf(j, 31) {
        int k = (1 << j) - A[i];
        if (A[i] == k ? m[k] >= 2 : m[k]) {
          --m[k];
          --m[A[i]];
          ++z;
          break;
        }
      }
    }
  }
  print(z);
  return 0;
}


Fixed submission:
#include <bits/stdc++.h>
#define fr(i, n) for (int i = 0; i < (n); ++i)
#define foor(i, a, b) for (int i = (a); i <= (b); ++i)
#define rf(i, n) for (int i = (n); i--;)
#define roof(i, b, a) for (int i = (b); i >= (a); --i)
#define elsif else if
#define all(x) x.begin(), x.end()
#define Sort(x) sort(all(x))
#define Reverse(x) reverse(all(x))
#define PQ priority_queue
#define NP(x) next_permutation(all(x))
#define M_PI 3.14159265358979323846
using namespace std;
typedef vector<bool> vb;
typedef vector<vb> vvb;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef unsigned long long ull;
typedef vector<ull> vu;
typedef vector<vu> vvu;
typedef double dbl;
typedef vector<dbl> vd;
typedef vector<vd> vvd;
typedef string str;
typedef vector<str> vs;
typedef vector<vs> vvs;
typedef pair<int, int> pii;
typedef vector<pii> vpii;
typedef map<int, int> mii;
typedef pair<ll, ll> pll;
typedef vector<pll> vpll;
typedef map<ll, ll> mll;
typedef pair<dbl, dbl> pdd;
typedef vector<pdd> vpdd;
typedef map<dbl, dbl> mdd;
typedef pair<str, str> pss;
typedef vector<pss> vpss;
typedef map<str, str> mss;
typedef pair<int, ll> pil;
typedef vector<pil> vpil;
typedef map<int, ll> mil;
typedef pair<ll, int> pli;
typedef vector<pli> vpli;
typedef map<ll, int> mli;
typedef pair<dbl, int> pdi;
typedef vector<pdi> vpdi;
typedef map<dbl, int> mdi;
template <typename T> vector<T> &operator<<(vector<T> &v, const T t) {
  v.push_back(t);
  return v;
}
template <typename T> multiset<T> &operator<<(multiset<T> &m, const T t) {
  m.insert(t);
  return m;
}
template <typename T> set<T> &operator<<(set<T> &s, const T t) {
  s.insert(t);
  return s;
}
template <typename T> stack<T> &operator<<(stack<T> &s, const T t) {
  s.push(t);
  return s;
}
template <typename T> queue<T> &operator<<(queue<T> &q, const T t) {
  q.push(t);
  return q;
}
template <typename T, typename U>
PQ<T, vector<T>, U> &operator<<(PQ<T, vector<T>, U> &q, const T t) {
  q.push(t);
  return q;
}
template <typename T, typename U>
istream &operator>>(istream &s, pair<T, U> &p) {
  return s >> p.first >> p.second;
}
template <typename T> istream &operator>>(istream &s, vector<T> &v) {
  fr(i, v.size()) { s >> v[i]; }
  return s;
}
template <typename T, typename U>
ostream &operator<<(ostream &s, const pair<T, U> p) {
  return s << p.first << " " << p.second;
}
// template<typename T>ostream&operator<<(ostream&s,const vector<T>v){for(auto
// a:v){s<<a<<endl;}return s;}
template <typename T> ostream &operator<<(ostream &s, const vector<T> v) {
  fr(i, v.size()) { i ? s << " " << v[i] : s << v[i]; }
  return s;
}
template <typename T, typename U>
pair<T, U> operator+(pair<T, U> a, pair<T, U> b) {
  return {a.first + b.first, a.second + b.second};
}
template <typename T, typename U>
pair<T, U> operator-(pair<T, U> a, pair<T, U> b) {
  return {a.first - b.first, a.second - b.second};
}
void print(void) { cout << endl; }
template <typename T> void print(T t) { cout << t << endl; }
template <typename T, typename... U> void print(T &&t, U &&...u) {
  cout << t << " ";
  print(forward<U>(u)...);
}
bool YN(bool b) {
  print(b ? "YES" : "NO");
  return b;
}
bool PI(bool b) {
  print(b ? "POSSIBLE" : "IMPOSSIBLE");
  return b;
}
bool Yn(bool b) {
  print(b ? "Yes" : "No");
  return b;
}
bool Pi(bool b) {
  print(b ? "Possible" : "Impossible");
  return b;
}
bool yn(bool b) {
  print(b ? "yes" : "no");
  return b;
}
bool pi(bool b) {
  print(b ? "possible" : "impossible");
  return b;
}
const int MD = 1e9 + 7;
template <typename T> str to_string(const T &n) {
  ostringstream s;
  s << n;
  return s.str();
}
template <typename T, typename U>
vector<pair<T, U>> dijkstra(const vector<vector<pair<T, U>>> E, const U s,
                            const T inf) {
  using P = pair<T, U>;
  vector<P> d;
  fr(i, E.size()) { d << P{inf, i}; }
  PQ<P, vector<P>, greater<P>> pq;
  pq << (d[s] = P{0, s});
  while (pq.size()) {
    P a = pq.top();
    pq.pop();
    U v = a.second;
    if (d[v].first >= a.first) {
      for (P e : E[v]) {
        if (d[v].first + e.first < d[e.second].first) {
          d[e.second] = P{d[v].first + e.first, v};
          pq << P{d[v].first + e.first, e.second};
        }
      }
    }
  }
  return d;
}
template <typename T, typename U>
map<U, pair<T, U>> dijkstra(map<U, vector<pair<T, U>>> E, const U s,
                            const T inf) {
  using P = pair<T, U>;
  map<U, P> d;
  for (pair<U, vector<P>> e : E) {
    d[e.first] = P{inf, e.first};
  }
  PQ<P, vector<P>, greater<P>> pq;
  pq << (d[s] = P{0, s});
  while (pq.size()) {
    P a = pq.top();
    pq.pop();
    U v = a.second;
    if (d[v].first >= a.first) {
      for (P e : E[v]) {
        if (d[v].first + e.first < d[e.second].first) {
          d[e.second] = P{d[v].first + e.first, v};
          pq << P{d[v].first + e.first, e.second};
        }
      }
    }
  }
  return d;
}
template <typename T> T distsq(pair<T, T> a, pair<T, T> b) {
  return (a.first - b.first) * (a.first - b.first) +
         (a.second - b.second) * (a.second - b.second);
}
template <typename T> T max(const vector<T> a) {
  T m = a[0];
  for (T e : a) {
    m = max(m, e);
  }
  return m;
}
template <typename T> T min(const vector<T> a) {
  T m = a[0];
  for (T e : a) {
    m = min(m, e);
  }
  return m;
}
template <typename T> T gcd(const T a, const T b) {
  return a ? gcd(b % a, a) : b;
}
template <typename T> T gcd(const vector<T> a) {
  T g = a[0];
  for (T e : a) {
    g = gcd(g, e);
  }
  return g;
}
template <typename T> vector<T> LIS(const vector<T> A) {
  vi B;
  for (T a : A) {
    auto it = lower_bound(all(B), a);
    if (it == B.end()) {
      B << a;
    } else {
      *it = a;
    }
  }
  return B;
}
template <typename T> vector<pair<T, T>> ConvexHull(vector<pair<T, T>> V) {
  if (V.size() <= 3) {
    return V;
  }
  Sort(V);
  rf(i, V.size() - 1) V << V[i];
  vector<pair<T, T>> r;
  for (pair<T, T> p : V) {
    int s = r.size();
    while (s >= 2 &&
           (p.second - r[s - 1].second) * (p.first - r[s - 2].first) <
               (p.second - r[s - 2].second) * (p.first - r[s - 1].first)) {
      r.pop_back();
      --s;
    }
    r << p;
  }
  r.pop_back();
  return r;
}
class UnionFind {
  vi p, r, s;

public:
  UnionFind(int N) {
    p = r = vi(N);
    s = vi(N, 1);
    fr(i, N) { p[i] = i; }
  }
  int find(int i) { return p[i] = p[i] == i ? i : find(p[i]); }
  void unite(int a, int b) {
    if (r[a = find(a)] > r[b = find(b)]) {
      swap(a, b);
    }
    s[b] += s[a];
    r[p[a] = b] += r[a] == r[b];
  }
  bool same(int a, int b) { return find(a) == find(b); }
  int size(int x) { return s[find(x)]; }
};
ll strmod(const str &s, const int m) {
  ll x = 0;
  fr(i, s.size()) { x = (x * 10 + s[i] - 48) % m; }
  return x;
}
vvl mul(const vvl &A, const vvl &B, const int m) {
  vvl C;
  fr(y, A.size()) { C << vl(B[y].size()); }
  fr(y, C.size()) {
    fr(x, C[y].size()) {
      fr(i, A[0].size()) { (C[y][x] += A[y][i] * B[i][x]) %= m; }
    }
  }
  return C;
}
vvl pow(const vvl &A, const ll n, const int m) {
  vvl B;
  fr(y, A.size()) { B << vl(A.size()); }
  if (n == 0) {
    fr(i, B.size()) { B[i][i] = 1; }
  }
  elsif(n % 2) { B = mul(A, pow(A, n - 1, m), m); }
  else {
    vvl C = pow(A, n / 2, m);
    B = mul(C, C, m);
  }
  return B;
}
ll pow(const ll a, const ll n, const int m) {
  ll t;
  return n ? (n & 1 ? a >= 0 ? a % m : (m - (-a % m)) % m : 1) *
                 (t = pow(a, n >> 1, m), t * t % m) % m
           : !!a;
}
ll inv(const ll x, const int p) { return pow(x, p - 2, p); }
ll inv(const ll x) { return inv(x, MD); }
vpll fact(const int n, const int p) {
  vpll v(n + 1);
  v[0].first = 1;
  foor(i, 1, n) { v[i].first = v[i - 1].first * i % p; }
  v[n].second = inv(v[n].first, p);
  roof(i, n, 1) { v[i - 1].second = v[i].second * i % p; }
  return v;
}
class Combination {
  const vpll f;
  const int M;

public:
  Combination(int n, int m) : f(fact(n, m)), M(m) {}
  Combination(int n) : Combination(n, MD) {}
  ll P(int n, int k) {
    return n < 0 || k < 0 || n < k ? 0ll : f[n].first * f[n - k].second % M;
  }
  ll C(int n, int k) { return P(n, k) * f[k].second % M; }
  ll H(int n, int k) { return n == 0 && k == 0 ? 1ll : C(n + k - 1, k); }
};
ll C2(const int n) { return (ll)n * ~-n / 2; }
ll sum(const vi a) {
  ll s = 0;
  for (int e : a) {
    s += e;
  }
  return s;
}
ll sum(const vl a) {
  ll s = 0;
  for (ll e : a) {
    s += e;
  }
  return s;
}
template <typename T> int MSB(T N) {
  int r = -1;
  for (; N > 0; N /= 2) {
    ++r;
  }
  return r;
}
template <typename T> class SegmentTree {
  vector<T> S;
  T (*const op)(T a, T b);
  const T zero;
  const int B;

public:
  SegmentTree(int N, T (*f)(T a, T b), const T zero)
      : S(1 << MSB(N - 1) + 2, zero), op(f), zero(zero),
        B(1 << MSB(N - 1) + 1) {}
  SegmentTree(vector<T> v, T (*f)(T a, T b), const T zero)
      : SegmentTree(v.size(), f, zero) {
    fr(i, v) { S[S.size() / 2 + i] = v[i]; }
    roof(i, S.size() / 2 - 1, 1) { S[i] = op(S[i * 2], S[i * 2 + 1]); }
  }
  T calc(int l, int r) {
    l += B;
    r += B;
    if (l > r) {
      return zero;
    }
    if (l == r) {
      return S[l];
    }
    T L = S[l], R = S[r];
    for (; l / 2 < r / 2; l /= 2, r /= 2) {
      if (l % 2 == 0) {
        L = op(L, S[l + 1]);
      }
      if (r % 2 == 1) {
        R = op(S[r - 1], R);
      }
    }
    return op(L, R);
  }
  void replace(int i, T x) {
    for (S[i += B] = x; i != 1; i /= 2) {
      if (i % 2) {
        S[i / 2] = op(S[i - 1], S[i]);
      } else {
        S[i / 2] = op(S[i], S[i + 1]);
      }
    }
  }
  void add(int i, T x) { replace(i, op(S[B + i], x)); }
  T top() { return S[1]; }
};
ll BITsum(vl &B, int i) {
  ll z = 0;
  while (i > 0) {
    z += B[i];
    i -= i & -i;
  }
  return z;
}
void BITadd(vl &B, int i, ll x) {
  while (i < B.size()) {
    B[i] += x;
    i += i & -i;
  }
}
ll fib(const ll n, const int m) {
  ll a, b, c, d, A, B, C, D;
  a = 1;
  b = 0;
  c = 0;
  d = 1;
  rf(i, 63) {
    A = a * a + b * c;
    B = a * b + b * d;
    C = c * a + d * c;
    D = c * b + d * d;
    if (n >> i & 1) {
      a = A;
      b = B;
      c = C;
      d = D;
      A = a + b;
      B = a;
      C = c + d;
      D = c;
    }
    a = A % m;
    b = B % m;
    c = C % m;
    d = D % m;
  }
  return b;
}
vi primes(int n) {
  vb b(n + 1);
  vi p;
  foor(i, 2, n) {
    if (!b[i]) {
      p << i;
      for (int j = 2 * i; j <= n; j += i) {
        b[j] = true;
      }
    }
  }
  return p;
}
vb isprime(const int n) {
  vb v(n + 1, true);
  v[0] = v[1] = false;
  foor(i, 2, n) {
    if (v[i]) {
      for (int j = 2 * i; j <= n; j += i) {
        v[j] = false;
      }
    }
  }
  return v;
}

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  int N;
  cin >> N;
  vi A(N);
  cin >> A;
  Sort(A);
  Reverse(A);
  int z = 0;
  mii m;
  fr(i, N) { ++m[A[i]]; }
  fr(i, N) {
    if (m[A[i]]) {
      rf(j, 31) {
        int k = (1 << j) - A[i];
        if (k <= 0)
          continue;
        if (A[i] == k ? m[k] >= 2 : m[k]) {
          --m[k];
          --m[A[i]];
          ++z;
          break;
        }
      }
    }
  }
  print(z);
  return 0;
}