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++ (GCC 9.2.1) (judge verdict: Accepted)

#include <bits/stdc++.h>
using namespace std;
#ifdef __DEBUG__
    void debug_out() { cerr << endl; } 
    template <typename Head, typename... Tail>
    void debug_out(Head H, Tail... T) {cerr << " " << H; debug_out(T...);}
    #define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#else
    #define debug(...) 
#endif

using ll = long long int;


inline void fast_io() { ios_base::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); };
template<typename T> inline ostream& operator<<(ostream& os, const vector<T>& v) { for (auto el : v) cout << el << " "; return os; }
template<typename T> inline vector<T> fetch_vec(int sz) { vector<T> ret(sz); for (auto& elem : ret) cin >> elem; return ret; }

int N;
vector<ll> A;
inline void input(){
    fast_io();
    cin >> N;
    A = fetch_vec<ll>(N+1);
}

map< int64_t, int > prime_factor(int64_t n) {
  map< int64_t, int > ret;
  for(int64_t i = 2; i * i <= n; i++) {
    while(n % i == 0) {
      ret[i]++;
      n /= i;
    }
  }
  if(n != 1) ret[n] = 1;
  return ret;
}

vector< bool > prime_table(int n) {
  vector< bool > prime(n + 1, true);
  if(n >= 0) prime[0] = false;
  if(n >= 1) prime[1] = false;
  for(int i = 2; i * i <= n; i++) {
    if(!prime[i]) continue;
    for(int j = i + i; j <= n; j += i) {
      prime[j] = false;
    }
  }
  return prime;
}


bool isok(ll p){
    if(A[0]%p) return false;
    if(p<=N){
        vector<ll> AP(p,0);
        for (int i = 0; i <= N; i++) AP[i%(p-1)] += A[i];
        for (int i = 0; i < p; i++) if(AP[i]%p) return false;
    }
    else{
        for (int i = 0; i <= N; i++) if(A[i]%p) return false;
    }
    return true;
}

inline void chmax(ll &a, ll b){if(a<b) a=b;}

int solve(){
    reverse(A.begin(),A.end());
    ll f1 = accumulate(A.begin(),A.end(),0LL);
    if(f1==0) f1 = abs(A[0]);
    // if(f1==0) {
    //     for (int i = 0; i <= N; i++)
    //     {
    //         if(i%2) f1 += A[i];
    //         else f1 -= A[i];
    //     }
    //     f1 = abs(f1);
    // }
    set<ll> ans;
    if(f1!=0){
        auto pf = prime_factor(abs(f1));
        for(auto [p,c]:pf){
            if(isok(p)) ans.insert(p);
        }
    }
    else{
        auto pt = prime_table(N);        
        for (int i = 2; i <= N; i++)
        {
            if(!pt[i]) continue;
            if(isok(i)) ans.insert(i);
        }

        f1 = abs(A[N]);
        auto pf = prime_factor(abs(f1));
        for(auto [p,c]:pf){
            if(isok(p)) ans.insert(p);
        }
    }

    for(auto a:ans) cout << a << endl;
    if(ans.empty()) cout << endl;
    return 0;
}   

int main()
{
    input();
    solve();
    return 0;
}