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: Time Limit Exceeded)

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;

namespace Contest
{
    class Scanner
    {
        private string[] line = new string[0];
        private int index = 0;

        public string Next()
        {
            if (line.Length <= index)
            {
                line = Console.ReadLine().Split(' ');
                index = 0;
            }

            var res = line[index];
            index++;
            return res;
        }

        public int NextInt()
        {
            return int.Parse(Next());
        }

        public long NextLong()
        {
            return long.Parse(Next());
        }

        public ulong NextUlong()
        {
            return ulong.Parse(Next());
        }

        public string[] Array()
        {
            line = Console.ReadLine().Split(' ');
            index = line.Length;
            return line;
        }

        public int[] IntArray()
        {
            var array = Array();
            var result = new int[array.Length];
            for (int i = 0; i < array.Length; i++)
            {
                result[i] = int.Parse(array[i]);
            }

            return result;
        }

        public long[] LongArray()
        {
            var array = Array();
            var result = new long[array.Length];
            for (int i = 0; i < array.Length; i++)
            {
                result[i] = long.Parse(array[i]);
            }

            return result;
        }
    }

    class Program
    {
        private int N;
        private int[] A;
        void Scan()
        {
            var sc = new Scanner();
            N = sc.NextInt();
            A = sc.IntArray();
        }

        public void Solve()
        {
            Scan();
            var set = new Set<int>();
            foreach (var i in A)
            {
                set.Insert(i);
            }
            Array.Sort(A, (a, b) => -a.CompareTo(b));
            int[] target = new int[N];
            int n = 1;

            for (int i = N - 1; i >= 0; i--)
            {

                if (n <= A[i])
                {
                    while (n <= A[i])
                    {
                        n *= 2;
                    }
                }

                target[i] = n;
            }

            int cnt = 0;
            for (int i = 0; i < N; i++)
            {
                var nA = set.LowerBound(A[i]);
                if (nA == null || nA.Val != A[i]) continue;
                set.Erase(A[i]);
                int t = target[i] - A[i];
                var tA = set.LowerBound(t);
                if (tA == null || tA.Val != t) continue;
                cnt++;
                set.Erase(t);

            }
            Console.WriteLine(cnt);
        }

        static void Main() => new Program().Solve();
    }


}

class Set<T>
{
    private Node Root;
    public int Count { get; private set; } = 0;
    private readonly Comparison<T> Compare;
    public Set() : this(Comparer<T>.Default) { }
    public Set(IComparer<T> comparer) : this(comparer.Compare) { }
    public Set(Comparison<T> comparison)
    {
        Compare = comparison;
    }
    public class Node
    {
        public T Val;
        public Node Parent, High, Low;
        public Node(T val, Node parent)
        {
            Val = val;
            Parent = parent;
        }
    }
    /// <summary>
    /// 要素の追加
    /// </summary>
    /// <param name="item">追加する要素</param>
    /// <returns></returns>
    public void Insert(T item)
    {
        if (Root == null)
        {
            Root = new Node(item, null);
            return;
        }
        Node node = Root;
        Node parent = null;
        bool high = false;
        while (node != null)
        {
            parent = node;
            if (Compare(item, node.Val) > 0)
            {
                node = node.High;
                high = true;
            }
            else
            {
                node = node.Low;
                high = false;
            }
        }
        node = new Node(item, parent);
        if (high)
        {
            parent.High = node;
        }
        else
        {
            parent.Low = node;
        }
    }
    /// <summary>
    /// 要素の削除
    /// </summary>
    /// <param name="item"></param>
    public void Erase(T item)
    {
        Node node = LowerBound(item);
        if (node == null) return;
        if (Compare(node.Val, item) == 0)
        {
            Erase(node);
        }
    }
    /// <summary>
    /// 要素の削除
    /// </summary>
    /// <param name="node"></param>
    public void Erase(Node node)
    {
        bool hasLow = node.Low != null;
        bool hasHigh = node.High != null;
        Node connect = null;
        if (hasHigh)
        {
            if (hasLow)
            {
                Node p = node;
                Node n = node.Low;
                while (n != null)
                {
                    p = n;
                    n = n.High;
                }
                node.Val = p.Val;
                Erase(p);
                return;
            }
            else
            {
                connect = node.High;
            }
        }
        else
        {
            if (hasLow)
            {
                connect = node.Low;
            }
            else
            {
                connect = null;
            }
        }
        var parent = node.Parent;
        if (connect != null)
        {
            connect.Parent = parent;
        }
        if (parent == null)
        {
            Root = connect;
        }
        else
        {
            if (Compare(node.Val, parent.Val) > 0)
            {
                parent.High = connect;
            }
            else
            {
                parent.Low = connect;
            }
        }
    }
    /// <summary>
    /// item以上の要素の検索
    /// </summary>
    /// <param name="item"></param>
    /// <returns></returns>
    public Node LowerBound(T item)
    {
        Node node = Root;
        Node parent = null;
        Node result = null;
        while (node != null)
        {
            parent = node;
            if (Compare(node.Val, item) >= 0)
            {
                if (result == null || Compare(result.Val, node.Val) > 0)
                {
                    result = node;
                }
                node = node.Low;
            }
            else
            {
                node = node.High;
            }
        }
        return result;
    }
    /// <summary>
    /// itemより大きい要素の検索
    /// </summary>
    /// <param name="item"></param>
    /// <returns></returns>
    public Node UpperBound(T item)
    {
        Node node = Root;
        Node parent = null;
        Node result = null;
        while (node != null)
        {
            parent = node;
            if (Compare(node.Val, item) > 0)
            {
                if (result == null || Compare(result.Val, node.Val) > 0)
                {
                    result = node;
                }
                node = node.Low;
            }
            else
            {
                node = node.High;
            }
        }
        return result;
    }
}