Problem:
Score : 300 points

Problem Statement

There are N people, conveniently numbered 1 through N.
They were standing in a row yesterday, but now they are unsure of the order in which they were standing.
However, each person remembered the following fact: the absolute difference of the number of the people who were standing to the left of that person, and the number of the people who were standing to the right of that person.
According to their reports, the difference above for person i is A_i.

Based on these reports, find the number of the possible orders in which they were standing.
Since it can be extremely large, print the answer modulo 10^9+7.
Note that the reports may be incorrect and thus there may be no consistent order.
In such a case, print 0.

Constraints

1≦N≦10^5

0≦A_i≦N-1

Input

The input is given from Standard Input in the following format:

N
A_1 A_2 ... A_N

Output

Print the number of the possible orders in which they were standing, modulo 10^9+7.

Sample Input 1

5
2 4 4 0 2

Sample Output 1

4

There are four possible orders, as follows:

2,1,4,5,3

2,5,4,1,3

3,1,4,5,2

3,5,4,1,2

Sample Input 2

7
6 4 0 2 4 0 2

Sample Output 2

0

Any order would be inconsistent with the reports, thus the answer is 0.

Sample Input 3

8
7 5 1 1 7 3 5 3

Sample Output 3

16

Solution in Rust (1.15.1) (judge verdict: Accepted)

use std::io::*;
use std::str::FromStr;
use std::collections::HashMap;
use std::collections::BTreeMap;
use std::collections::BTreeSet;
use std::collections::HashSet;
use std::cmp;
use std::f64::consts;
use std::cmp::Ordering;
use std::collections::VecDeque; //push_back, pop_front

const MOD: i64 = 1000000007;

fn main() {
    let n: i64 = read();
    let vec: Vec<i64> = (0..n).map(|_| read()).collect();
    let mut map: HashMap<i64, i64> = HashMap::new();

    for &i in vec.iter() {
        *map.entry(i).or_insert(0)+=1;
    }

    let mut isOk = true;

    for (&key, &value) in map.iter() {
        if n % 2 == 0 {
            if value != 2 {
                isOk = false;
                break;
            }
        } else {
            if value != 2 {
                if key != 0 {
                    isOk = false;
                }
            }
        }
    }

    let mut ans: i64 = 0;

    if isOk {
        ans = 1;
        for i in 0..n/2 {
            ans = ans * 2 % MOD;
        }
    }

    println!("{}", ans);
}

// 素因数分解
fn prime_factorization(number: u64) -> Vec<u64> {
    let mut result = number;
    for i in 2..((number as f64).sqrt() as u64)+1 {
        if number % i == 0 {
            result = i;
            break;
        }
    }

    if result == number {
        return vec![number];
    } else {
        let mut v1 = vec![result];
        let mut v2 = prime_factorization(number / result);

        v1.append(&mut v2);

        return v1;
    }
}

fn calc_distance(xa: f64, ya: f64, xb: f64, yb: f64)->f64 {
    (f64::powf(xb-xa, 2.0) + f64::powf(yb-ya, 2.0)).sqrt()
}

fn calc_triangle_area(x1: f64, y1: f64, x2: f64, y2: f64, x3: f64, y3: f64) -> f64 {
    1.0/2.0 * ((x1-x3)*(y2-y3)-(x2-x3)*(y1-y3)).abs()
}

fn read<T: FromStr>() -> T {
    let stdin = stdin();
    let stdin = stdin.lock();
    let token: String = stdin
        .bytes()
        .map(|c| c.expect("failed to read char") as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .collect();
    token.parse().ok().expect("failed to parse token")
}

// 最大公約数
fn gcd(a: i64, b: i64) -> i64 {
    match b {
        0 => a,
        _ => gcd(b, a % b)
    }
}

// 最小公倍数
fn lcm(a: i64, b: i64) -> i64 {
    let g = gcd(a ,b);
    a / g * b
}

// 階乗-dp (overflow回避で1000000007の余りを使って計算)
fn kaijou_dp(n: i64) -> i64 {
    let mut dp: Vec<i64> = vec![0; n as usize+1];
    dp[0] = 1;
    dp[1] = 1;

    for i in 1..n {
        dp[i as usize+1] = dp[i as usize] % 1000000007 * (i+1)  % 1000000007;
    }
    return dp[n as usize];
}

// 階乗
fn kaijou(n: i64)->i64 {
    if n == 1 {
        return n;
    }
    return n * kaijou(n-1);
}

// 順列全列挙
pub trait LexicalPermutation {
    /// Return `true` if the slice was permuted, `false` if it is already
    /// at the last ordered permutation.
    fn next_permutation(&mut self) -> bool;
}

impl<T> LexicalPermutation for [T] where T: Ord {
    /// Original author in Rust: Thomas Backman <serenity@exscape.org>
    /// let mut data = [1, 2, 3];
    //    let mut permutations = Vec::new();
    //
    //    loop {
    //        permutations.push(data.to_vec());
    //        if !data.next_permutation() {
    //            break;
    //        }
    //    }
    //
    //    println!("{:?}", permutations);
    //    // [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
    fn next_permutation(&mut self) -> bool {
        // These cases only have 1 permutation each, so we can't do anything.
        if self.len() < 2 { return false; }

        // Step 1: Identify the longest, rightmost weakly decreasing part of the vector
        let mut i = self.len() - 1;
        while i > 0 && self[i-1] >= self[i] {
            i -= 1;
        }

        // If that is the entire vector, this is the last-ordered permutation.
        if i == 0 {
            return false;
        }

        // Step 2: Find the rightmost element larger than the pivot (i-1)
        let mut j = self.len() - 1;
        while j >= i && self[j] <= self[i-1]  {
            j -= 1;
        }

        // Step 3: Swap that element with the pivot
        self.swap(j, i-1);

        // Step 4: Reverse the (previously) weakly decreasing part
        self[i..].reverse();

        true
    }
}

//iより小さい数字の数 = lower_bound(&a, i) as i64;
//iより大きい数字の数 = n - upper_bound(&c, i) as i64;
fn lower_bound<T: Ord>(vec: &Vec<T>, x: T) -> usize {
    let (mut left, mut right): (i64, i64) = (-1, vec.len() as i64);

    while (right - left) > 1 {
        let mid = (right + left) / 2;

        if x <= vec[mid as usize] {
            right = mid;
        } else {
            left = mid;
        }
    }

    return right as usize;
}

fn upper_bound<T: Ord>(vec: &Vec<T>, x: T) -> usize {
    let (mut left, mut right): (i64, i64) = (-1, vec.len() as i64);

    while (right - left) > 1 {
        let mid = (right + left) / 2;

        if x < vec[mid as usize] {
            right = mid;
        } else {
            left = mid;
        }
    }

    return right as usize;
}