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.Text;
using System.Linq;
using System.Collections.Generic;


class Program {

	const long mod = 1000000007;
	//public static int[] max;


	static void Main(string[] args) {

		char[] cs = new char[] { ' ', ',' };
		//int val = int.Parse(Console.ReadLine());
		//int[] vals = parseAry(Console.ReadLine().Split(cs));
		//string str = Console.ReadLine();
		//string[] strs = Console.ReadLine().Split(cs);

		//string res="";
		//int res = 0; ;
		//int t = int.Parse(Console.ReadLine());
		//string str = Console.ReadLine();
		///int[] vals = parseAry(Console.ReadLine().Split(cs));
		//int n = int.Parse(Console.ReadLine());

		//int num = vals[0];

		int res = 0;
		int n = int.Parse(Console.ReadLine());
		int[] vals = parseAry(Console.ReadLine().Split(cs));


		PriorityQueue pq = new PriorityQueue();
		for ( int i = 0; i < vals.Length; i++ ) {
			pq.Enqueue(new PriQ() { rank = vals[i] });		
		}
		while ( pq.Count > 0 ) {
			if ( pq.Count <= 1 ) { break; }
			int x = pq.DequeueLast().rank;
			int c = -1;
			for ( int i = 1 << 30; i > 0; i = i >> 1 ) {
				if ( ( x & i ) == i ) { c = i << 1; break; }
			}
			int find = c - x;
			int k = pq.Binary_SearchX(find);
			if ( k != -1 ) {
				pq.Remove(k);
				res++;
			}else{}
		}
			Console.WriteLine(res);

		return;
	}
	//　String[]  ----->  int[]
	static int[] parseAry(string[] str) {
		int[] nums = new int[str.Length];
		for ( int i = 0; i < str.Length; i++ ) { nums[i] = int.Parse(str[i]); }
		return nums;
	}
	//　String[]  ----->  long[]
	static long[] parseAryL(string[] str) {
		long[] nums = new long[str.Length];
		for ( int i = 0; i < str.Length; i++ ) { nums[i] = long.Parse(str[i]); }
		return nums;
	}

	//文字列を1文字ずつString[]に入れる
	static string[] strAry(String str) {
		string[] re = new string[str.Length];
		for ( int i = 0; i < str.Length; i++ ) { re[i] = str[i].ToString(); }
		return re;
	}

}
public class PriQ {
	public int rank { get; set; }
	public string rankstr { get; set; }
	public int num { get; set; }
	public int[] nums { get; set; }
	public Object obj { get; set; }
	public PriQ() { }
}

public class PriorityQueue {
	List<PriQ> list = new List<PriQ>();
	public PriorityQueue() { }
	public PriorityQueue(PriQ p) { list.Add(p); }
	public void Enqueue(PriQ item) { list.Insert(Binary_Search(item), item); }
	public PriQ Dequeue() { PriQ r = list[0]; list.RemoveAt(0); return r; }
	public PriQ DequeueLast() { PriQ r = list[list.Count - 1]; list.RemoveAt(list.Count - 1); return r; }
	public PriQ Peek() { return list[0]; }
	public PriQ Get(int n) { return list[n]; }
	public PriQ Last() { return list[list.Count - 1]; }
	public void Remove(int n) { list.RemoveAt(n); }
	public int Count { get { return list.Count; } }

	private int Binary_Search(PriQ pq) {
		long Lower = 0;
		long Upper = list.Count - 1;
		while ( Lower <= Upper ) {
			long Center = ( Lower + Upper ) >> 1;
			if ( pq.rank > list[(int)Center].rank ) {
				Lower = Center + 1;
			} else if ( pq.rank < list[(int)Center].rank ) {
				Upper = Center - 1;
			} else {
				return (int)Center;
			}
		}
		return (int)Lower;
	}
	public int Binary_SearchX(int x) {
		long Lower = 0;
		long Upper = list.Count - 1;
		while ( Lower <= Upper ) {
			long Center = ( Lower + Upper ) >> 1;
			if ( x > list[(int)Center].rank ) {
				Lower = Center + 1;
			} else if ( x < list[(int)Center].rank ) {
				Upper = Center - 1;
			} else {
				return (int)Center;
			}
		}
		return -1;
	}
}