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 Rust (1.42.0) (judge verdict: Accepted)

use std::io;
use std::cmp;
use std::collections::BinaryHeap;
use std::collections::HashMap;
use std::collections::HashSet;
use std::f64::consts::PI;
use std::str::FromStr;

type Error = Box<dyn std::error::Error>;

fn read_line() -> String {
    let mut buf = String::new();
    io::stdin().read_line(&mut buf).ok();
    buf
}

struct Scanner {
    buff: Vec<String>,
    pos: usize,
}


impl Scanner {
    pub fn new() -> Self {
        Scanner {
            buff: Vec::new(),
            pos: 0,
        }
    }

    pub fn next<T: FromStr>(&mut self) -> T {
        while self.buff.len() <= self.pos {
            self.pos = 0;
            self.buff = read_line().split_whitespace().map(|s| s.to_owned()).collect();
        }

        let result = self.buff[self.pos].parse::<T>();
        self.pos += 1;
        result.ok().unwrap()
    }

    pub fn next_line(&mut self) -> String {
        let result  = read_line().trim().to_owned();
        self.buff.clear();
        self.pos = 0;

        result
    }

    pub fn next_vec<T: FromStr>(&mut self) -> Vec<T> {
        self.buff.clear();
        self.pos = 0;
        read_line().trim().split_whitespace().map(|s| s.parse().ok().unwrap()).collect()
    }
    
    pub fn next_line_chars(&mut self) -> Vec<char> {
        let result  = read_line().trim().chars().collect();
        self.buff.clear();
        self.pos = 0;

        result
    }
}

#[derive(Clone)]
struct Edge<T: Clone> {
    to: usize,
    cap: T,
    rev: usize,
}

pub struct Graph<T: Clone> {
    edges: Vec<Vec<Edge<T>>>,
}

impl<T: Clone> Graph<T> {
    pub fn new(n: usize) -> Self {
        Graph {
            edges: vec![Vec::new(); n],
        }
    }
}

impl Graph<i64> {

    pub fn add_edge(&mut self, from: usize, to: usize, cap: i64) {
        let flen = self.edges[from].len();
        let tlen = self.edges[to].len();
        self.edges[from].push(Edge { to, cap, rev: tlen });
        self.edges[to].push(Edge { to: from, cap: 0, rev: flen });
    }

    fn dfs(&mut self, v: usize, t: usize, f: i64, used: &mut Vec<bool>) -> i64 {
        if v == t {
            return f;
        }
        used[v] = true;
        for i in 0..self.edges[v].len() {
            let eto = self.edges[v][i].to;
            let ecap = self.edges[v][i].cap;
            let erev = self.edges[v][i].rev;
            if !used[eto] && ecap > 0 {
                let d = self.dfs(eto, t, std::cmp::min(f, ecap), used);
                if d > 0 {
                    self.edges[v][i].cap -= d;
                    self.edges[eto][erev].cap += d;
                    return d;
                }
            }
        }
        0
    }

    pub fn max_flow(&mut self, s: usize, t: usize, inf: i64) -> i64 {
        let mut flow = 0;
        let mut used = vec![false; self.edges.len()];
        loop {
            used.iter_mut().for_each(|x| *x = false);
            let f = self.dfs(s, t, inf, &mut used);
            if f == 0 {
                return flow;
            }
            flow += f;
        }
    }
}

fn main() {
    let mut scan = Scanner::new();
    let n: usize = scan.next();
    let mut a: Vec<u64> = scan.next_vec();
    a.sort();
    let mut memo: HashMap<u64, usize> = HashMap::new();
    let mut b = Vec::new();
    let mut rb: HashMap<u64, usize> = HashMap::new();
    for i in 0..n {
        let s = *memo.get(&a[i]).unwrap_or(&0);
        if s == 0 {
            rb.insert(a[i], b.len());
            b.push(a[i]);
        }
        memo.insert(a[i], s+1);
    }

    let n = memo.len();
    
    let mut ans = 0;
    for i in (0..n).rev() {
        let mut tar = 1;
        while tar <= b[i] {
            tar *= 2;
        }
        let tar = tar - b[i];
        if tar == b[i] {
            let d = *memo.get(&tar).unwrap_or(&0)/2;
            memo.get_mut(&b[i]).map(|m| *m -= d*2);
            ans += d;
        } else {
            let v = *memo.get(&b[i]).unwrap_or(&0);
            let w = *memo.get(&tar).unwrap_or(&0);
            let d = cmp::min(v, w);
            memo.get_mut(&b[i]).map(|m| *m -= d);
            memo.get_mut(&tar).map(|m| *m -= d);
            ans += d;
        }
    }
    println!("{}", ans);
}