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

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
using static System.Console;
using static System.Math;
class Z { static void Main() => new K(); }
class K
{
	int F => int.Parse(Str);
	long FL => long.Parse(Str);
	int[] G => Strs.Select(int.Parse).ToArray();
	uint[] GU => Strs.Select(uint.Parse).ToArray();
	decimal[] GD => Strs.Select(decimal.Parse).ToArray();
	long[] GL => Strs.Select(long.Parse).ToArray();
	string Str => ReadLine();
	string[] Strs => Str.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
	static T[] ConstantArray<T>(int n, T val) { var a = new T[n]; for (var i = 0; i < n; i++) a[i] = val; return a; }
	static T[] MakeArray<T>(int n, Func<int, T> f) { var a = new T[n]; for (var i = 0; i < n; i++) a[i] = f(i); return a; }
	static ulong One(int k) => 1ul << k;
	static ulong All(int k) => One(k) - 1;
	static bool Has(ulong s, int k) => (s & One(k)) != 0;
	const int MOD = 1000000007;
	public K()
	{
		SetOut(new StreamWriter(OpenStandardOutput()) { AutoFlush = false });
		Solve();
		Out.Flush();
	}
	void Solve()
	{
		var N = F;
		var a = new int[N + 1];
		for (var i = 0; i <= N; i++) a[N - i] = F;
		var g = a[N];
		if (g < 0) g = -g;
		for (var i = 0; i <= N; i++) g = GCD(g, a[i]);
		for (var i = 0; i <= N; i++) a[i] /= g;
		var ps = GetPrimes(10010);
		var ok = new SortedSet<long>(Factorize(g, ps).Keys);
		{
			var b = new long[2];
			b[0] = a[0] % 2;
			for (var i = 1; i <= N; i++) b[1] = (b[1] + a[i]) % 2;
			if (b.All(x => x == 0)) ok.Add(2);
		}
		foreach (var p in ps)
		{
			if (ok.Contains(p)) continue;
			if (p > N + 10) continue;
			if (a[0] % p != 0) continue;
			if (p == 2) continue;
			// x^(p-1)==1 => p-2 次
			var b = new long[p - 1];
			for (var i = 0; i <= N; i++)
			{
				var k = i % (p - 1);
				b[k] = (b[k] + a[i]) % p;
			}
			if (b.All(x => x == 0)) ok.Add(p);
		}
		foreach (var p in ok) WriteLine(p);
	}
	public static int GCD(int n, int m)
	{
		if (n < 0) n = -n;
		if (m < 0) m = -m;
		while (m > 0)
		{
			var c = n % m;
			n = m;
			m = c;
		}
		return n;
	}
	public static Dictionary<long, int> Factorize(long n, List<int> primes)
	{
		var d = new Dictionary<long, int>();
		for (var j = 0; j < primes.Count; j++)
		{
			var i = primes[j];
			if (i * i > n) break;
			if (n % i == 0)
			{
				d.Add(i, 0);
				while (n % i == 0) { n /= i; d[i]++; }
			}
		}
		if (n > 1) d.Add(n, 1);
		return d;
	}
	public static List<int> GetPrimes(int n)
	{
		if (n < 3) n = 3;
		var m = (n - 1) >> 1;
		var primes = new List<int>((int)(n / Math.Log(n)));
		primes.Add(2);
		var composites = new bool[m];
		composites[0] = false;
		for (var p = 0; p < m; p++)
		{
			if (!composites[p])
			{
				var pnum = 2 * p + 3;
				primes.Add(pnum);
				for (var k = 3 * p + 3; k < m; k += pnum) composites[k] = true;
			}
		}
		return primes;
	}
}