Problem:
Score : 800 points

Problem Statement

You are given a polynomial of degree N with integer coefficients: f(x)=a_Nx^N+a_{N-1}x^{N-1}+...+a_0. Find all prime numbers p that divide f(x) for every integer x.

Constraints

0 \leq N \leq 10^4

|a_i| \leq 10^9(0\leq i\leq N)

a_N \neq 0

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N
a_N
:
a_0

Output

Print all prime numbers p that divide f(x) for every integer x, in ascending order.

Sample Input 1

2
7
-7
14

Sample Output 1

2
7

2 and 7 divide, for example, f(1)=14 and f(2)=28.

Sample Input 2

3
1
4
1
5

Sample Output 2

There may be no integers that satisfy the condition.

Sample Input 3

0
998244353

Sample Output 3

998244353

Solution in C++14 (GCC 5.4.1) (judge verdict: Wrong Answer)

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iostream>
#include <map>
#include <memory>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <unordered_map>
#include <vector>

using namespace std;

typedef long long lint;

typedef complex<__float128> doublex;
struct FFT {
  vector<doublex> fft(vector<doublex> y, bool invert = false) {
    const int N = y.size(); assert(N == (N&-N));
    vector<int> rev(N);
    for (int i = 1; i < N; ++i) {
      rev[i] = (rev[i>>1]>>1) | (i&1 ? N>>1 : 0);
      if (rev[i] < i) swap(y[i], y[rev[i]]);
    }
    vector<doublex> rootni(N/2);
    for (int n = 2; n <= N; n *= 2) {
      const doublex rootn = polar(1.0l, (invert ? +1.0 : -1.0) * 2.0*M_PIl/n);
      rootni[0] = 1.0;
      for (int i = 1; i < n/2; ++i) rootni[i] = rootni[i-1] * rootn;
      for (int left = 0; left != N; left += n) {
	const int mid = left + n/2;
	for (int i = 0; i < n/2; ++i) {
	  const doublex temp = rootni[i] * y[mid + i];
	  y[mid + i] = y[left + i] - temp; y[left + i] += temp;
	}
      }
    } if (invert) for (auto &v : y) v /= (doublex)N;
    return move(y);
  }
};

lint gcd(lint a, lint b) {
  if (a == 0) return b;
  return gcd(b%a, a);
}

bool eval(const vector<int> &poly, int x, lint mod) {
  lint result = 0;
  for (int i = (int)poly.size() - 1; i >= 0; --i) {
    result = ((__int128)result * x + poly[i]) % mod;
    if (result < 0) result += mod;
  }
  return result;
}

bool prime_divides(lint p, const vector<int> &poly) {
  for (int rep = 0; rep < 20; ++rep) {
    lint x = rand() % p;
    if (eval(poly, x, p) != 0) {
      return false;
    }
  }
  return true;
}

int main() {
  int n;
  vector<doublex> poly(1<<16);
  scanf("%d", &n);
  vector<int> poly_int(n + 1);
  for (int i = n; i >= 0; --i) {
    int val;
    scanf("%d", &val);
    poly[i] = val;
    poly_int[i] = val;
  }
  FFT fft;
  vector<doublex> res = fft.fft(poly);
  lint g = 0;
  for (int i = 0; i < (int)res.size(); ++i) {
    __float128 v2 = real(res[i]) * real(res[i]) + imag(res[i]) * imag(res[i]);
    if (v2 < 0) v2 = -v2;
    lint l = 0, r = abs((lint)real(res[i])) + abs((lint)imag(res[i])) + 10;
    while (l < r) {
      lint m = l + (r - l + 1) / 2;
      if ((__float128)m * m > v2 + 0.5) r = m - 1;
      else l = m;
    }
    g = gcd(g, l);
  }

  vector<lint> primes;
  for (lint p = 2; p * p <= g; ++p)
    if (g % p == 0) {
      do {
        g /= p;
      } while (g % p == 0);
      primes.push_back(p);
    }
  if (g > 1) {
    primes.push_back(g);
    g = 1;
  }

  for (lint p : primes)
    if (prime_divides(p, poly_int))
      printf("%lld\n", p);

  return 0;
}