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 C# (Mono 4.6.2.0) (judge verdict: Accepted)

#region using
using System;
using System.Collections.Generic;
using System.Linq;
using IEnumerable = System.Collections.IEnumerable;
using IEnumerator = System.Collections.IEnumerator;
using BitArray = System.Collections.BitArray;
using BigInteger = System.Numerics.BigInteger;
using TextReader = System.IO.TextReader;
using System.Text;
#endregion

namespace AtCoderProject
{
    public class Program
    {
        public object Calc()
        {
            var N = consoleReader.Int;
            var a = consoleReader.Split.Int;
            var sorted = a.OrderByDescending(i => i).ToArray();

            for (int i = 0; i < N / 2; i++)
            {
                if (sorted[2 * i + 1] != (N - 2 * i - 1) || sorted[2 * i] != sorted[2 * i + 1])
                    return 0;
            }
            if (N % 2 == 1 && sorted[N - 1] != 0)
                return 0;
            return Mod.Pow(2, N/2);
        }
        struct Mod : IEquatable<Mod>
        {
            public const long mod = 1000000007;
            public readonly long val;
            public Mod(long val) { this.val = val; }
            public override bool Equals(object obj) => (obj is Mod) ? this == ((Mod)obj) : false;
            public bool Equals(Mod obj) => this == obj;
            public override int GetHashCode() => val.GetHashCode();
            public override string ToString() => val.ToString();
            public static implicit operator Mod(long x) => new Mod(x);
            public static Mod operator +(Mod x, Mod y) => (x.val + y.val) % mod;
            public static Mod operator -(Mod x, Mod y) => x.val >= y.val ? (x.val - y.val) % mod : (x.val - y.val) % mod + mod;
            public static Mod operator *(Mod x, Mod y) => (x.val * y.val) % mod;
            public static Mod operator /(Mod x, Mod y) => x * y.Inverse();
            public static bool operator ==(Mod x, Mod y) => x.val == y.val;
            public static bool operator !=(Mod x, Mod y) => x.val != y.val;
            public Mod Inverse()
            {
                long a = val, b = mod, u = 1, v = 0;
                while (b > 0)
                {
                    long t = a / b;
                    var b2 = a - t * b;
                    a = b; b = b2;
                    var v2 = u - t * v;
                    u = v; v = v2;
                }
                u %= mod;
                if (u < 0) u += mod;
                return u;
            }
            public static Mod Pow(Mod x, int y)
            {
                Mod res = 1;
                for (; y > 0; y >>= 1)
                {
                    if ((y & 1) == 1) res *= x;
                    x *= x;
                }
                return res;
            }

            public static Factor CreateFactor(int max) => new Factor(max);
            public class Factor
            {
                private readonly Mod[] fac, finv;
                public Factor(int max)
                {
                    ++max;
                    var inv = new Mod[max];
                    fac = new Mod[max]; finv = new Mod[max];
                    fac[0] = fac[1] = 1;
                    finv[0] = finv[1] = 1;
                    inv[1] = 1;
                    for (int i = 2; i < max; i++)
                    {
                        fac[i] = fac[i - 1] * i;
                        inv[i] = mod - inv[mod % i].val * (mod / i) % mod;
                        finv[i] = finv[i - 1] * inv[i];
                    }
                }

                // 二項係数計算
                public Mod Combine(int n, int k)
                {
                    if (n < k) return 0;
                    if (n < 0 || k < 0) return 0;
                    return fac[n] * finv[k] * finv[n - k];
                }

                public Mod Factorial(int n) => fac[n];
                public Mod FactorialInvers(int n) => finv[n];
            }
        }

        #region いつもの
#pragma warning disable
        [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] private ConsoleReader consoleReader;
        public Program(ConsoleReader consoleReader) { this.consoleReader = consoleReader; }
        static void Main() => Console.WriteLine(new Program(new ConsoleReader(Console.In)).Calc()); static string AllLines<T>(IEnumerable<T> source) => string.Join("\n", source);
    }
    static class Ext
    {
        public static Dictionary<TKey, int> GroupCount<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) => source.GroupBy(keySelector).ToDictionary(g => g.Key, g => g.Count());
        public static Dictionary<TKey, int> GroupCount<TKey>(this IEnumerable<TKey> source) => source.GroupCount(i => i);
    }
    public class ConsoleReader { private string[] ReadLineSplit() => textReader.ReadLine().Split(Array.Empty<char>(), StringSplitOptions.RemoveEmptyEntries); private string[] line = Array.Empty<string>(); private int linePosition; private TextReader textReader; public ConsoleReader(TextReader tr) { textReader = tr; } public int Int => int.Parse(String); public long Long => long.Parse(String); public double Double => double.Parse(String); public string String { get { if (linePosition >= line.Length) { linePosition = 0; line = ReadLineSplit(); } return line[linePosition++]; } } public class SplitLine { private string[] splited; public SplitLine(ConsoleReader cr) { splited = cr.ReadLineSplit(); cr.line = Array.Empty<string>(); } public int[] Int => String.Select(x => int.Parse(x)).ToArray(); public int[] Int0 => String.Select(x => int.Parse(x) - 1).ToArray(); public long[] Long => String.Select(x => long.Parse(x)).ToArray(); public double[] Double => String.Select(x => double.Parse(x)).ToArray(); public string[] String => splited; } public SplitLine Split => new SplitLine(this); public class RepeatReader : IEnumerable<ConsoleReader> { ConsoleReader cr; int count; public RepeatReader(ConsoleReader cr, int count) { this.cr = cr; this.count = count; } public IEnumerator<ConsoleReader> GetEnumerator() => Enumerable.Repeat(cr, count).GetEnumerator(); System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); public IEnumerable<string> String => this.Select(cr => cr.String); public IEnumerable<int> Int => this.Select(cr => cr.Int); public IEnumerable<int> Int0 => this.Select(cr => cr.Int - 1); public IEnumerable<long> Long => this.Select(cr => cr.Long); public IEnumerable<double> Double => this.Select(cr => cr.Double); } public RepeatReader Repeat(int count) => new RepeatReader(this, count); }
    #endregion
}