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 <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;
using namespace std;

template<class T> ostream& operator<<(ostream &os, vector<T> V) {
 os << "[ "; for(auto v : V) os << v << " "; return os << "]";}
template<class L, class R> ostream& operator<<(ostream &os, pair<L,R> P) {
	return os << "(" << P.first << "," << P.second << ")";}

#define TRACE
#ifdef TRACE
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
	cout << name << " : " << arg1 << std::endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
	const char* comma = strchr(names + 1, ',');cout.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
}
#else
#define trace(...) 1
#endif


#define ll long long
#define ld long double
#define vll vector<ll>
#define pll pair<ll,ll>
#define vpll vector<pll>
#define I insert 
#define pb push_back
#define F first
#define S second
#define endl "\n"

const ll MAX = 1e4+15; 
set<ll> ans;
vll v;ll gc;
ll n;
ll pr[MAX];
void sieve(){
	// cout<<gc;
	ll i,j,k;
	for(i=2;i<=n+2;i++)pr[i] = i;
	for(i=2;i<=n+2;i++){
		if(pr[i]!=i)continue;
		ll a=0;bool is = true;
		for(j=0;j<i-1;j++){
			a=0;
			for(k=j;k<=n;k+=i-1){
				a+=v[k];
			}
			if(a<0) { a = i - (abs(a)%i);  }  
			// trace(j,a,v[0]);
			if(i==2){if(!(((v[0]%2)==0)&&((a%2)==0)))is = false; continue;}
			if(a%i){is= false;break;}
		}
		if(is)ans.I(i);
		for(j=i+i;j<MAX;j+=i){
			pr[j] = min(pr[j],i);
		}
	}
	for(i=2;i*i<=gc;i++){
		if(gc%i)continue;
		while((gc%i)==0)gc/=i;
		ans.I(i);
	}
	if(gc!=1)ans.I(gc);
}
int main(){
	ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);cout<<setprecision(25);
	ll a,b,c,i,j,k;
	cin>>n;
	for(i=0;i<=n;i++){
		cin>>a;v.pb(a);
		if(i==0)b=abs(a);else b=__gcd(b,abs(a));
	}
	gc = b;
	reverse(v.begin(),v.end());
	sieve();
	for(auto z:ans)cout<<z<<"\n";
}