Problem p03065 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
using namespace std;
// type alias
typedef long long LL;
typedef pair<int, int> II;
typedef tuple<int, int, int> III;
typedef vector<int> VI;
typedef vector<string> VS;
typedef unordered_map<int, int> MAPII;
typedef unordered_set<int> SETI;
template <class T> using VV = vector<vector<T>>;
// minmax
template <class T> inline T SMIN(T &a, const T b) {
  return a = (a > b) ? b : a;
}
template <class T> inline T SMAX(T &a, const T b) {
  return a = (a < b) ? b : a;
}
// repetition
#define FORE(i, a, b) for (int i = (a); i <= (b); ++i)
#define REPE(i, n) for (int i = 0; i <= (n); ++i)
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define REP(i, n) for (int i = 0; i < (n); ++i)
#define FORR(x, arr) for (auto &x : arr)
#define SZ(a) int((a).size())
// collection
#define ALL(c) (c).begin(), (c).end()
// DP
#define MINUS(dp) memset(dp, -1, sizeof(dp))
#define ZERO(dp) memset(dp, 0, sizeof(dp))
// stdout
#define println(args...) fprintf(stdout, ##args), putchar('\n');
// debug cerr
template <class Iter> void __kumaerrc(Iter begin, Iter end) {
  for (; begin != end; ++begin) {
    cerr << *begin << ',';
  }
  cerr << endl;
}
void __kumaerr(istream_iterator<string> it) {
  (void)it;
  cerr << endl;
}
template <typename T, typename... Args>
void __kumaerr(istream_iterator<string> it, T a, Args... args) {
  cerr << *it << "=" << a << ", ", __kumaerr(++it, args...);
}
template <typename S, typename T>
std::ostream &operator<<(std::ostream &_os, const std::pair<S, T> &_p) {
  return _os << "{" << _p.first << ',' << _p.second << "}";
}
#define __KUMATRACE__ true
#ifdef __KUMATRACE__
#define dump(args...)                                                          \
  {                                                                            \
    string _s = #args;                                                         \
    replace(_s.begin(), _s.end(), ',', ' ');                                   \
    stringstream _ss(_s);                                                      \
    istream_iterator<string> _it(_ss);                                         \
    __kumaerr(_it, args);                                                      \
  }
#define dumpc(ar)                                                              \
  {                                                                            \
    cerr << #ar << ": ";                                                       \
    FORR(x, (ar)) { cerr << x << ','; }                                        \
    cerr << endl;                                                              \
  }
#define dumpC(beg, end)                                                        \
  {                                                                            \
    cerr << "~" << #end << ": ";                                               \
    __kumaerrc(beg, end);                                                      \
  }
#else
#define dump(args...)
#define dumpc(ar)
#define dumpC(beg, end)
#endif

// $ cp-batch PolynomialDivisors | diff PolynomialDivisors.out -
// $ g++ -std=c++14 -Wall -O2 -D_GLIBCXX_DEBUG -fsanitize=address
// PolynomialDivisors.cpp && ./a.out

/*

 4/22/2019

 14:03-14:30 give up

 polynomial <=> ? (How can we use this conditin?)
 ∀x s.t. pred(x) <=> ? (How can we use ∀x condition?)

 14:30- read editorials

 It turns out that first step is a|b <=> b≡0 (mod a)


 http://drken1215.hatenablog.com/entry/2019/04/21/004100
 https://qiita.com/drken/items/6b4031ccbb2cab7436f3

 */

const int MAX_N = 1e4 + 1;
LL A[MAX_N];
int N;

LL gcd(LL a, LL b) { return b == 0 ? a : gcd(b, a % b); }
vector<int> sieve(int N) {
  if (N <= 0)
    return {};
  vector<int> fs(N + 1, true);
  fs[0] = fs[1] = false;
  for (int p = 2; p * p <= N; ++p)
    if (fs[p]) {
      for (int q = p * p; q <= N; q += p)
        fs[q] = false;
    }
  vector<int> res;
  for (int n = 2; n <= N; ++n)
    if (fs[n])
      res.push_back(n);
  return res;
}

vector<LL> primeFactors(LL n) {
  assert(n >= 1);
  vector<LL> res;
  for (LL p = 2; p * p <= n; ++p)
    while (n % p == 0) {
      res.push_back(p);
      n /= p;
    }
  if (n > 1)
    res.push_back(n);
  return res;
}
void solve() {
  set<LL> res;
  LL g = A[0];
  REP(i, N + 1) g = gcd(g, A[i]);
  vector<LL> X = primeFactors(g);
  FORR(a, X) res.emplace(a);

  vector<int> P = sieve(N);
  //  dumpc(P);
  FORR(p, P) {
    vector<LL> C(p);
    REP(n, p) C[n] = A[n] % p;
    FORE(n, p, N) {
      int nn = n % (p - 1);
      if (nn == 0)
        nn = p - 1;
      C[nn] = (C[nn] + A[n] % p) % p;
    }
    bool ok = true;
    REP(i, p) ok &= (C[i] % p == 0);
    if (ok)
      res.emplace(p);
  }
  FORR(p, res) cout << p << endl;
}

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout << setprecision(12) << fixed;

  cin >> N;
  REP(i, N + 1) cin >> A[i];
  reverse(A, A + N + 1);
  solve();

  return 0;
}


Fixed submission:
#include <bits/stdc++.h>
using namespace std;
// type alias
typedef long long LL;
typedef pair<int, int> II;
typedef tuple<int, int, int> III;
typedef vector<int> VI;
typedef vector<string> VS;
typedef unordered_map<int, int> MAPII;
typedef unordered_set<int> SETI;
template <class T> using VV = vector<vector<T>>;
// minmax
template <class T> inline T SMIN(T &a, const T b) {
  return a = (a > b) ? b : a;
}
template <class T> inline T SMAX(T &a, const T b) {
  return a = (a < b) ? b : a;
}
// repetition
#define FORE(i, a, b) for (int i = (a); i <= (b); ++i)
#define REPE(i, n) for (int i = 0; i <= (n); ++i)
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define REP(i, n) for (int i = 0; i < (n); ++i)
#define FORR(x, arr) for (auto &x : arr)
#define SZ(a) int((a).size())
// collection
#define ALL(c) (c).begin(), (c).end()
// DP
#define MINUS(dp) memset(dp, -1, sizeof(dp))
#define ZERO(dp) memset(dp, 0, sizeof(dp))
// stdout
#define println(args...) fprintf(stdout, ##args), putchar('\n');
// debug cerr
template <class Iter> void __kumaerrc(Iter begin, Iter end) {
  for (; begin != end; ++begin) {
    cerr << *begin << ',';
  }
  cerr << endl;
}
void __kumaerr(istream_iterator<string> it) {
  (void)it;
  cerr << endl;
}
template <typename T, typename... Args>
void __kumaerr(istream_iterator<string> it, T a, Args... args) {
  cerr << *it << "=" << a << ", ", __kumaerr(++it, args...);
}
template <typename S, typename T>
std::ostream &operator<<(std::ostream &_os, const std::pair<S, T> &_p) {
  return _os << "{" << _p.first << ',' << _p.second << "}";
}
#define __KUMATRACE__ true
#ifdef __KUMATRACE__
#define dump(args...)                                                          \
  {                                                                            \
    string _s = #args;                                                         \
    replace(_s.begin(), _s.end(), ',', ' ');                                   \
    stringstream _ss(_s);                                                      \
    istream_iterator<string> _it(_ss);                                         \
    __kumaerr(_it, args);                                                      \
  }
#define dumpc(ar)                                                              \
  {                                                                            \
    cerr << #ar << ": ";                                                       \
    FORR(x, (ar)) { cerr << x << ','; }                                        \
    cerr << endl;                                                              \
  }
#define dumpC(beg, end)                                                        \
  {                                                                            \
    cerr << "~" << #end << ": ";                                               \
    __kumaerrc(beg, end);                                                      \
  }
#else
#define dump(args...)
#define dumpc(ar)
#define dumpC(beg, end)
#endif

// $ cp-batch PolynomialDivisors | diff PolynomialDivisors.out -
// $ g++ -std=c++14 -Wall -O2 -D_GLIBCXX_DEBUG -fsanitize=address
// PolynomialDivisors.cpp && ./a.out

/*

 4/22/2019

 14:03-14:30 give up

 polynomial <=> ? (How can we use this conditin?)
 ∀x s.t. pred(x) <=> ? (How can we use ∀x condition?)

 14:30- read editorials

 It turns out that first step is a|b <=> b≡0 (mod a)


 http://drken1215.hatenablog.com/entry/2019/04/21/004100
 https://qiita.com/drken/items/6b4031ccbb2cab7436f3

 */

const int MAX_N = 1e4 + 1;
LL A[MAX_N];
int N;

LL gcd(LL a, LL b) { return b == 0 ? a : gcd(b, a % b); }
vector<int> sieve(int N) {
  if (N <= 0)
    return {};
  vector<int> fs(N + 1, true);
  fs[0] = fs[1] = false;
  for (int p = 2; p * p <= N; ++p)
    if (fs[p]) {
      for (int q = p * p; q <= N; q += p)
        fs[q] = false;
    }
  vector<int> res;
  for (int n = 2; n <= N; ++n)
    if (fs[n])
      res.push_back(n);
  return res;
}

vector<LL> primeFactors(LL n) {
  assert(n >= 1);
  vector<LL> res;
  for (LL p = 2; p * p <= n; ++p)
    while (n % p == 0) {
      res.push_back(p);
      n /= p;
    }
  if (n > 1)
    res.push_back(n);
  return res;
}
void solve() {
  set<LL> res;
  LL g = A[0];
  REP(i, N + 1) g = gcd(abs(g), abs(A[i]));
  vector<LL> X = primeFactors(g);
  FORR(a, X) res.emplace(a);

  vector<int> P = sieve(N);
  //  dumpc(P);
  FORR(p, P) {
    vector<LL> C(p);
    REP(n, p) C[n] = A[n] % p;
    FORE(n, p, N) {
      int nn = n % (p - 1);
      if (nn == 0)
        nn = p - 1;
      C[nn] = (C[nn] + A[n] % p) % p;
    }
    bool ok = true;
    REP(i, p) ok &= (C[i] % p == 0);
    if (ok)
      res.emplace(p);
  }
  FORR(p, res) cout << p << endl;
}

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout << setprecision(12) << fixed;

  cin >> N;
  REP(i, N + 1) cin >> A[i];
  reverse(A, A + N + 1);
  solve();

  return 0;
}