Problem:
Score : 600 points

Problem Statement

Takahashi has N balls with positive integers written on them. The integer written on the i-th ball is A_i.
He would like to form some number of pairs such that the sum of the integers written on each pair of balls is a power of 2.
Note that a ball cannot belong to multiple pairs.
Find the maximum possible number of pairs that can be formed.

Here, a positive integer is said to be a power of 2 when it can be written as 2^t using some non-negative integer t.

Constraints

1 \leq N \leq 2\times 10^5

1 \leq A_i \leq 10^9

A_i is an integer.

Input

Input is given from Standard Input in the following format:

N
A_1 A_2 ... A_N

Output

Print the maximum possible number of pairs such that the sum of the integers written on each pair of balls is a power of 2.

Sample Input 1

3
1 2 3

Sample Output 1

1

We can form one pair whose sum of the written numbers is 4 by pairing the first and third balls.
Note that we cannot pair the second ball with itself.

Sample Input 2

5
3 11 14 5 13

Sample Output 2

2

Solution in C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using SB = System.Text.StringBuilder;
//using System.Threading.Tasks;
//using System.Text.RegularExpressions;
//using System.Globalization;
//using System.Diagnostics;
using static System.Console;
using System.Numerics;
using static System.Math;
using pair = Pair<int, int>;

class Program
{
    static void Main()
    {
        //SetOut(new StreamWriter(OpenStandardOutput()) { AutoFlush = false });
        new Program().solve();
        Out.Flush();
    }
    readonly Scanner cin = new Scanner();
    readonly int[] dd = { 0, 1, 0, -1, 0 }; //→↓←↑
    readonly int mod = 1000000007;
    readonly int dom = 998244353;
    bool chmax<T>(ref T a, T b) where T : IComparable<T> { if (a.CompareTo(b) < 0) { a = b; return true; } return false; }
    bool chmin<T>(ref T a, T b) where T : IComparable<T> { if (b.CompareTo(a) < 0) { a = b; return true; } return false; }

    void solve()
    {
        int N = cin.nextint;
        var A = cin.scanlong;

        var H = new HashMap<long, int>();
        for (int i = 0; i < N; i++)
        {
            if (H.ContainsKey(-A[i]))
            {
                H[-A[i]]++;
            }
            else
            {
                H[-A[i]] = 1;
            }
        }
        var target = (long)1 << 31;
        int ans = 0;
        var W = new HashMap<long, int>();


        foreach (var v in H)
        {
            var y = -v.Key;
            while (y * 2 < target)
            {
                target >>= 1;
            }
            var x = target - y;

            if (x == y)
            {
                int w = v.Value -W[y];
                ans += w / 2;
                W[y] += w / 2;
            }
            else
            {
                if (H.ContainsKey(-x))
                {
                    int w = H[-x];
                    int s = Min(w - W[x], v.Value - W[y]);

                    W[x] += s;
                    W[y] += s;
                    ans += s;
                }
            }
        }
        WriteLine(ans);


        //var used = new bool[N];
        //Array.Sort(A);
        //var L = A.ToList();
        //int cnt = 0;

        //var target = (long)1 << 31;

        //while (L.Count > 0)
        //{
        //    var y = L[L.Count - 1];
        //    while (y * 2 < target)
        //    {
        //        target >>= 1;
        //    }
        //    var x = target - y;
        //    var idx = L.lower_bound(x);
        //    var u = L.upper_bound(x);
        //    //WriteLine(x + " " + y);

        //    if (x == y)
        //    {
        //        if (u - idx > 1)
        //        {
        //            cnt++;
        //            L.RemoveAt(idx);
        //        }
        //    }
        //    else if (u - idx > 0)
        //    {
        //        cnt++;
        //        L.RemoveAt(idx);
        //    }

        //    L.RemoveAt(L.Count - 1);
        //}
        //WriteLine(cnt);

    }

}

class HashMap<TKey, TValue> : SortedDictionary<TKey, TValue>
{
    public new TValue this[TKey key]
    {
        get
        {
            TValue value;
            return TryGetValue(key, out value) ? value : default(TValue);
        }
        set
        {
            base[key] = value;
        }
    }
}


static class Ex
{
    public static void join<T>(this IEnumerable<T> values, string sep = " ") => WriteLine(string.Join(sep, values));
    public static string concat<T>(this IEnumerable<T> values) => string.Concat(values);
    public static string reverse(this string s) { var t = s.ToCharArray(); Array.Reverse(t); return t.concat(); }

    public static int lower_bound<T>(this IList<T> arr, T val) where T : IComparable<T>
    {
        int low = 0, high = arr.Count;
        int mid;
        while (low < high)
        {
            mid = ((high - low) >> 1) + low;
            if (arr[mid].CompareTo(val) < 0) low = mid + 1;
            else high = mid;
        }
        return low;
    }
    public static int upper_bound<T>(this IList<T> arr, T val) where T : IComparable<T>
    {
        int low = 0, high = arr.Count;
        int mid;
        while (low < high)
        {
            mid = ((high - low) >> 1) + low;
            if (arr[mid].CompareTo(val) <= 0) low = mid + 1;
            else high = mid;
        }
        return low;
    }
}

class Pair<T, U> : IComparable<Pair<T, U>> where T : IComparable<T> where U : IComparable<U>
{
    public T f; public U s;
    public Pair(T f, U s) { this.f = f; this.s = s; }
    public int CompareTo(Pair<T, U> a) => f.CompareTo(a.f) != 0 ? f.CompareTo(a.f) : s.CompareTo(a.s);
    public override string ToString() => $"{f} {s}";
}

class Scanner
{
    string[] s; int i;
    readonly char[] cs = new char[] { ' ' };
    public Scanner() { s = new string[0]; i = 0; }
    public string[] scan => ReadLine().Split();
    public int[] scanint => Array.ConvertAll(scan, int.Parse);
    public long[] scanlong => Array.ConvertAll(scan, long.Parse);
    public double[] scandouble => Array.ConvertAll(scan, double.Parse);
    public string next
    {
        get
        {
            if (i < s.Length) return s[i++];
            string st = ReadLine();
            while (st == "") st = ReadLine();
            s = st.Split(cs, StringSplitOptions.RemoveEmptyEntries);
            i = 0;
            return next;
        }
    }
    public int nextint => int.Parse(next);
    public long nextlong => long.Parse(next);
    public double nextdouble => double.Parse(next);
}