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 Rust (1.15.1) (judge verdict: Accepted)

//! ----------------------------------------------
//! Framework <https://github.com/vain0x/procon>
//!
//! See the bottom of file for solution.
//! ----------------------------------------------

#![allow(unused_imports)]
#![allow(non_snake_case)]

use std::cell::RefCell;
use std::cmp::{max, min, Ordering};
use std::collections::*;
use std::fmt::{Debug, Display, Formatter, Write as FmtWrite};
use std::io::{stderr, stdin, BufRead, Write};
use std::mem::{replace, swap};
use std::ops::*;
use std::rc::Rc;

/// Print values to standard error if debug mode.
#[allow(unused_macros)]
macro_rules! debug {
    ($($e:expr),*) => {
        #[cfg(debug_assertions)]
        $({
            let (e, mut err) = (stringify!($e), stderr());
            writeln!(err, "\x1B[33m{}\x1B[0m = {:?}", e, $e).unwrap()
        })*
    };
}

/// Read from standard input and parse each word.
/// - `read!(T, U, ..)` parses a line as a tuple of words.
/// - `read![[T]]` parses a line as an array of words.
/// - `read![..; N]` parses `N` lines, using `read!(..)` repeatedly.
#[allow(unused_macros)]
macro_rules! read {
    ([$t:ty] ; $n:expr) =>
        ((0..$n).map(|_| read!([$t])).collect::<Vec<_>>());
    ($($t:ty),+ ; $n:expr) =>
        ((0..$n).map(|_| read!($($t),+)).collect::<Vec<_>>());
    ([$t:ty]) =>
        (rl().split_whitespace().map(|w| w.parse().unwrap()).collect::<Vec<$t>>());
    ($($t:ty),*) => {{
        let buf = rl();
        let mut w = buf.split_whitespace();
        ($(w.next().unwrap().parse::<$t>().unwrap()),*)
    }};
}

/// Read a line from standard input.
#[allow(dead_code)]
fn rl() -> String {
    let mut buf = String::new();
    stdin().read_line(&mut buf).unwrap();

    #[allow(deprecated)]
    buf.trim_right().to_owned()
}

// -----------------------------------------------
// Solution
// -----------------------------------------------

pub fn gcd(x: i64, y: i64) -> i64 {
    if y == 0 {
        x.abs()
    } else {
        gcd(y, x % y)
    }
}

/// Performs the sieve of Eratosthenes.
/// O(n log (log n)) time.
pub fn sieve(n: usize) -> Vec<bool> {
    let mut sieve = vec![true; max(2, n)];
    sieve[0] = false;
    sieve[1] = false;

    for p in 2..n {
        if !sieve[p] {
            continue;
        }

        let mut k = 2 * p;
        while k < n {
            sieve[k] = false;
            k += p;
        }
    }

    sieve
}

/// Performs prime factorization in O(√x) time.
pub fn factorize(mut x: i64) -> BTreeMap<i64, i64> {
    let mut ms = BTreeMap::new();
    let r = (x as f64).sqrt() as i64 + 1;

    for p in 2..r as i64 {
        let mut m = 0;

        while x >= p && x % p == 0 {
            x /= p;
            m += 1;
        }

        if m > 0 {
            ms.insert(p, m);
        }
    }

    // `x` can have a prime factor larger than √x at most one.
    if x > 1 {
        ms.insert(x, 1);
    }

    ms
}

// mod p において多項式 A が x^p - x で割り切れるならOK
fn ok(p: usize, A: &[i64], B: &mut [i64]) -> bool {
    for i in 0..A.len() {
        B[i] = A[i];
    }

    let N = A.len() - 1;

    for k in (0..N + 1).rev() {
        // debug!((k, p), B);

        // -c * x^(k - p) * (x^p - x) を足して x^k の項を消す。
        if k >= p {
            let c = B[k];
            B[k] = 0;
            B[k - p + 1] += c;
        }

        if B[k] % (p as i64) != 0 {
            return false;
        }
    }
    true
}

fn main() {
    let N = read!(usize);
    let mut A = read![i64; N + 1];
    A.reverse();

    // 係数の最大公約数 g
    // f(x) は明らかに g の倍数になるので g の素因数はすべて解に含まれる。
    let mut g = A[0];
    for &a in &A {
        g = gcd(g, a);
    }
    let g_factors = factorize(g);

    // 係数列が互いに素になるようにしておく
    for a in &mut A {
        *a /= g;
    }

    // debug!(g_factors);

    // 2..=N の素数については全通り試す
    let sieve = sieve(N + 1);

    let mut B = A.to_owned();

    let mut ps = (2..N + 1)
        .filter(|&p| sieve[p] && ok(p, &A, &mut B))
        .chain(g_factors.keys().map(|&p| p as usize))
        .collect::<Vec<_>>();
    ps.sort();
    ps.dedup();

    for p in ps {
        println!("{}", p);
    }
}