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 Java8 (OpenJDK 1.8.0) (judge verdict: Accepted)

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Iterator;
import java.io.BufferedWriter;
import java.util.Set;
import java.util.InputMismatchException;
import java.util.Random;
import java.io.IOException;
import java.util.HashSet;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.util.NoSuchElementException;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 * @author GYSHGX868
 */
public class Main {
  public static void main(String[] args) {
    InputStream inputStream = System.in;
    OutputStream outputStream = System.out;
    InputReader in = new InputReader(inputStream);
    OutputWriter out = new OutputWriter(outputStream);
    TaskC solver = new TaskC();
    solver.solve(1, in, out);
    out.close();
  }

  static class TaskC {
    public void solve(int testNumber, InputReader in, OutputWriter out) {
      int n = in.nextInt();
      int[] a = IOUtils.readIntArray(in, n);
      boolean[] visited = new boolean[n];
      Set<IntIntPair> set = new HashSet<>();
      IntSet same = new IntHashSet();
      for (int i = 0; i < n; i++) {
        int left = (n - a[i] - 1) / 2;
        int right = (n + a[i] - 1) / 2;
        if (left == right && same.contains(left)) {
          out.printLine(0);
          return;
        } else if (left == right) {
          same.add(left);
        }
        if (left != right) {
          set.add(IntIntPair.makePair(left, right));
        }
        visited[left] = visited[right] = true;
      }
      for (int i = 0; i < n; i++) {
        if (!visited[i]) {
          out.printLine(0);
          return;
        }
      }
      out.printLine(IntegerUtils.fastPower(2, set.size(), MiscUtils.MOD7));
    }

  }

  static class IntArray extends IntAbstractStream implements IntList {
    private int[] data;

    public IntArray(int[] arr) {
      data = arr;
    }

    public int size() {
      return data.length;
    }

    public int get(int at) {
      return data[at];
    }

    public void addAt(int index, int value) {
      throw new UnsupportedOperationException();
    }

    public void removeAt(int index) {
      throw new UnsupportedOperationException();
    }

  }

  static interface IntCollection extends IntStream {
    int size();

    default void add(int value) {
      throw new UnsupportedOperationException();
    }

    default IntCollection addAll(IntStream values) {
      for (IntIterator it = values.intIterator(); it.isValid(); it.advance()) {
        add(it.value());
      }
      return this;
    }

  }

  static class MiscUtils {
    public static final int MOD7 = (int) (1e9 + 7);

    private MiscUtils() {
    }

  }

  static class IOUtils {
    private IOUtils() {
    }

    public static int[] readIntArray(InputReader in, int size) {
      int[] array = new int[size];
      for (int i = 0; i < size; i++) {
        array[i] = in.nextInt();
      }
      return array;
    }

  }

  static class InputReader {
    private InputStream stream;
    private byte[] buf = new byte[1024];
    private int curChar;
    private int numChars;
    private InputReader.SpaceCharFilter filter;

    public InputReader(InputStream stream) {
      this.stream = stream;
    }

    public int read() {
      if (numChars == -1) {
        throw new InputMismatchException();
      }
      if (curChar >= numChars) {
        curChar = 0;
        try {
          numChars = stream.read(buf);
        } catch (IOException e) {
          throw new InputMismatchException();
        }
        if (numChars <= 0) {
          return -1;
        }
      }
      return buf[curChar++];
    }

    public int nextInt() {
      int c = read();
      while (isSpaceChar(c)) {
        c = read();
      }
      int sgn = 1;
      if (c == '-') {
        sgn = -1;
        c = read();
      }
      int res = 0;
      do {
        if (c < '0' || c > '9') {
          throw new InputMismatchException();
        }
        res *= 10;
        res += c - '0';
        c = read();
      } while (!isSpaceChar(c));
      return res * sgn;
    }

    public boolean isSpaceChar(int c) {
      if (filter != null) {
        return filter.isSpaceChar(c);
      }
      return isWhitespace(c);
    }

    public static boolean isWhitespace(int c) {
      return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
    }

    public interface SpaceCharFilter {
      boolean isSpaceChar(int ch);

    }

  }

  static class IntegerUtils {
    private IntegerUtils() {
    }

    public static int gcd(int a, int b) {
      a = Math.abs(a);
      b = Math.abs(b);
      while (b != 0) {
        int temp = a % b;
        a = b;
        b = temp;
      }
      return a;
    }

    public static long fastPower(long base, long exponent, long mod) {
      if (exponent == 0) {
        return 1 % mod;
      }
      if (base >= mod) {
        base %= mod;
      }
      long result = 1;
      while (exponent != 0) {
        if ((exponent & 1) == 1) {
          result = result * base % mod;
        }
        base = base * base % mod;
        exponent >>>= 1;
      }
      return result;
    }

  }

  static interface IntList extends IntReversibleCollection {
    public abstract int get(int index);

    public abstract void addAt(int index, int value);

    public abstract void removeAt(int index);

    public default IntIterator intIterator() {
      return new IntIterator() {
        private int at;
        private boolean removed;


        public int value() {
          if (removed) {
            throw new IllegalStateException();
          }
          return get(at);
        }


        public boolean advance() {
          at++;
          removed = false;
          return isValid();
        }


        public boolean isValid() {
          return !removed && at < size();
        }


        public void remove() {
          removeAt(at);
          at--;
          removed = true;
        }
      };
    }

    public default void add(int value) {
      addAt(size(), value);
    }

  }

  static interface IntReversibleCollection extends IntCollection {
  }

  static class IntHash {
    private IntHash() {
    }

    public static int hash(int c) {
      return c;
    }

  }

  static class IntHashSet extends IntAbstractStream implements IntSet {
    private static final Random RND = new Random();
    private static final int[] SHIFTS = new int[4];
    private static final byte PRESENT_MASK = 1;
    private static final byte REMOVED_MASK = 2;
    private int size;
    private int realSize;
    private int[] values;
    private byte[] present;
    private int step;
    private int ratio;

    static {
      for (int i = 0; i < 4; i++) {
        SHIFTS[i] = RND.nextInt(31) + 1;
      }
    }

    public IntHashSet() {
      this(3);
    }

    public IntHashSet(int capacity) {
      capacity = Math.max(capacity, 3);
      values = new int[capacity];
      present = new byte[capacity];
      ratio = 2;
      initStep(capacity);
    }

    public IntHashSet(IntCollection c) {
      this(c.size());
      addAll(c);
    }

    public IntHashSet(int[] arr) {
      this(new IntArray(arr));
    }

    private void initStep(int capacity) {
      step = RND.nextInt(capacity - 2) + 1;
      while (IntegerUtils.gcd(step, capacity) != 1) {
        step++;
      }
    }

    public IntIterator intIterator() {
      return new IntIterator() {
        private int position = size == 0 ? values.length : -1;


        public int value() throws NoSuchElementException {
          if (position == -1) {
            advance();
          }
          if (position >= values.length) {
            throw new NoSuchElementException();
          }
          if ((present[position] & PRESENT_MASK) == 0) {
            throw new IllegalStateException();
          }
          return values[position];
        }


        public boolean advance() throws NoSuchElementException {
          if (position >= values.length) {
            throw new NoSuchElementException();
          }
          position++;
          while (position < values.length && (present[position] & PRESENT_MASK) == 0) {
            position++;
          }
          return isValid();
        }


        public boolean isValid() {
          return position < values.length;
        }


        public void remove() {
          if ((present[position] & PRESENT_MASK) == 0) {
            throw new IllegalStateException();
          }
          present[position] = REMOVED_MASK;
        }
      };
    }

    public int size() {
      return size;
    }

    public void add(int value) {
      ensureCapacity((realSize + 1) * ratio + 2);
      int current = getHash(value);
      while (present[current] != 0) {
        if ((present[current] & PRESENT_MASK) != 0 && values[current] == value) {
          return;
        }
        current += step;
        if (current >= values.length) {
          current -= values.length;
        }
      }
      while ((present[current] & PRESENT_MASK) != 0) {
        current += step;
        if (current >= values.length) {
          current -= values.length;
        }
      }
      if (present[current] == 0) {
        realSize++;
      }
      present[current] = PRESENT_MASK;
      values[current] = value;
      size++;
    }

    private int getHash(int value) {
      int hash = IntHash.hash(value);
      int result = hash;
      for (int i : SHIFTS) {
        result ^= hash >> i;
      }
      result %= values.length;
      if (result < 0) {
        result += values.length;
      }
      return result;
    }

    private void ensureCapacity(int capacity) {
      if (values.length < capacity) {
        capacity = Math.max(capacity * 2, values.length);
        rebuild(capacity);
      }
    }

    private void rebuild(int capacity) {
      initStep(capacity);
      int[] oldValues = values;
      byte[] oldPresent = present;
      values = new int[capacity];
      present = new byte[capacity];
      size = 0;
      realSize = 0;
      for (int i = 0; i < oldValues.length; i++) {
        if ((oldPresent[i] & PRESENT_MASK) == PRESENT_MASK) {
          add(oldValues[i]);
        }
      }
    }

    public boolean contains(int value) {
      int current = getHash(value);
      while (present[current] != 0) {
        if (values[current] == value && (present[current] & PRESENT_MASK) != 0) {
          return true;
        }
        current += step;
        if (current >= values.length) {
          current -= values.length;
        }
      }
      return false;
    }

  }

  static interface IntStream extends Iterable<Integer>, Comparable<IntStream> {
    IntIterator intIterator();

    default Iterator<Integer> iterator() {
      return new Iterator<Integer>() {
        private IntIterator it = intIterator();


        public boolean hasNext() {
          return it.isValid();
        }


        public Integer next() {
          if (!hasNext()) {
            throw new NoSuchElementException();
          }
          int result = it.value();
          it.advance();
          return result;
        }
      };
    }

    default int compareTo(IntStream c) {
      IntIterator it = intIterator();
      IntIterator jt = c.intIterator();
      while (it.isValid() && jt.isValid()) {
        int i = it.value();
        int j = jt.value();
        if (i < j) {
          return -1;
        } else if (i > j) {
          return 1;
        }
        it.advance();
        jt.advance();
      }
      if (it.isValid()) {
        return 1;
      }
      if (jt.isValid()) {
        return -1;
      }
      return 0;
    }

    default boolean contains(int value) {
      for (IntIterator it = intIterator(); it.isValid(); it.advance()) {
        if (it.value() == value) {
          return true;
        }
      }
      return false;
    }

  }

  static interface IntIterator {
    int value() throws NoSuchElementException;

    boolean advance();

    boolean isValid();

  }

  static class OutputWriter {
    private final PrintWriter writer;

    public OutputWriter(OutputStream outputStream) {
      writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
    }

    public OutputWriter(Writer writer) {
      this.writer = new PrintWriter(writer);
    }

    public void close() {
      writer.close();
    }

    public void printLine(long i) {
      writer.println(i);
    }

    public void printLine(int i) {
      writer.println(i);
    }

  }

  static interface IntSet extends IntCollection {
  }

  static class IntIntPair implements Comparable<IntIntPair> {
    public final int first;
    public final int second;

    public IntIntPair(int first, int second) {
      this.first = first;
      this.second = second;
    }

    public static IntIntPair makePair(int first, int second) {
      return new IntIntPair(first, second);
    }

    public boolean equals(Object o) {
      if (this == o) {
        return true;
      }
      if (o == null || getClass() != o.getClass()) {
        return false;
      }
      IntIntPair pair = (IntIntPair) o;
      return first == pair.first && second == pair.second;
    }

    public int hashCode() {
      int result = first;
      result = 31 * result + second;
      return result;
    }

    public String toString() {
      return "(" + first + ", " + second + ")";
    }

    public int compareTo(IntIntPair o) {
      int value = Integer.compare(first, o.first);
      if (value != 0) {
        return value;
      }
      return Integer.compare(second, o.second);
    }

  }

  static abstract class IntAbstractStream implements IntStream {
    public String toString() {
      return toString(" ");
    }

    public String toString(String separator) {
      StringBuilder builder = new StringBuilder();
      boolean first = true;
      for (IntIterator it = intIterator(); it.isValid(); it.advance()) {
        if (first) {
          first = false;
        } else {
          builder.append(separator);
        }
        builder.append(it.value());
      }
      return builder.toString();
    }

    public boolean equals(Object o) {
      if (!(o instanceof IntStream)) {
        return false;
      }
      IntStream c = (IntStream) o;
      IntIterator it = intIterator();
      IntIterator jt = c.intIterator();
      while (it.isValid() && jt.isValid()) {
        if (it.value() != jt.value()) {
          return false;
        }
        it.advance();
        jt.advance();
      }
      return !it.isValid() && !jt.isValid();
    }

    public int hashCode() {
      int result = 0;
      for (IntIterator it = intIterator(); it.isValid(); it.advance()) {
        result *= 31;
        result += it.value();
      }
      return result;
    }

  }
}