Problem p03842 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
using namespace std;

using ll = long long;
using pii = pair<int, int>;
template <class T> using V = vector<T>;
template <class T> using VV = V<V<T>>;

#define pb push_back
#define eb emplace_back
#define mp make_pair
#define fi first
#define se second
#define rep(i, n) rep2(i, 0, n)
#define rep2(i, m, n) for (int i = m; i < (n); i++)
#define per(i, b) per2(i, 0, b)
#define per2(i, a, b) for (int i = int(b) - 1; i >= int(a); i--)
#define ALL(c) (c).begin(), (c).end()
#define SZ(x) ((int)(x).size())

constexpr ll TEN(int n) { return (n == 0) ? 1 : 10 * TEN(n - 1); }

template <class T, class U> void chmin(T &t, const U &u) {
  if (t > u)
    t = u;
}
template <class T, class U> void chmax(T &t, const U &u) {
  if (t < u)
    t = u;
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  os << "(" << p.first << "," << p.second << ")";
  return os;
}

template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
  os << "{";
  rep(i, v.size()) {
    if (i)
      os << ",";
    os << v[i];
  }
  os << "}";
  return os;
}

#ifdef LOCAL
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 << __LINE__ << " [" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#define dump(x) cerr << __LINE__ << " " << #x << " = " << (x) << endl
#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif

template <unsigned int MOD> struct ModInt {
  using uint = unsigned int;
  using ull = unsigned long long;
  using M = ModInt;

  uint v;

  ModInt(ll _v = 0) { set_norm(_v % MOD + MOD); }
  M &set_norm(uint _v) { //[0, MOD * 2)->[0, MOD)
    v = (_v < MOD) ? _v : _v - MOD;
    return *this;
  }

  explicit operator bool() const { return v != 0; }
  M operator+(const M &a) const { return M().set_norm(v + a.v); }
  M operator-(const M &a) const { return M().set_norm(v + MOD - a.v); }
  M operator*(const M &a) const { return M().set_norm(ull(v) * a.v % MOD); }
  M operator/(const M &a) const { return *this * a.inv(); }
  M &operator+=(const M &a) { return *this = *this + a; }
  M &operator-=(const M &a) { return *this = *this - a; }
  M &operator*=(const M &a) { return *this = *this * a; }
  M &operator/=(const M &a) { return *this = *this / a; }
  M operator-() const { return M() - *this; }
  M &operator++(int) { return *this = *this + 1; }
  M &operator--(int) { return *this = *this - 1; }

  M pow(ll n) const {
    if (n < 0)
      return inv().pow(-n);
    M x = *this, res = 1;
    while (n) {
      if (n & 1)
        res *= x;
      x *= x;
      n >>= 1;
    }
    return res;
  }

  M inv() const {
    ll a = v, b = MOD, p = 1, q = 0, t;
    while (b != 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(p -= t * q, q);
    }
    return M(p);
  }

  bool operator==(const M &a) const { return v == a.v; }
  bool operator!=(const M &a) const { return v != a.v; }
  friend ostream &operator<<(ostream &os, const M &a) { return os << a.v; }
  static uint get_mod() { return MOD; }
};

using Mint = ModInt<1000000007>;

struct SCC {
  int n;
  VV<int> g, rg;
  V<int> vs, cmp;
  V<bool> vis;

  SCC() {}
  SCC(int n) : n(n) {
    g = rg = VV<int>(n);
    vs = cmp = V<int>(n);
    vis = V<bool>(n);
  }

  void add_edge(int from, int to) {
    g[from].push_back(to);
    rg[to].push_back(from);
  }

  void dfs(int v) {
    vis[v] = true;

    for (int to : g[v]) {
      if (!vis[to]) {
        dfs(to);
      }
    }

    vs.push_back(v);
  }

  void rdfs(int v, int k, V<int> &vec) {
    vis[v] = true;
    cmp[v] = k;
    vec.push_back(v);

    for (int to : rg[v]) {
      if (!vis[to]) {
        rdfs(to, k, vec);
      }
    }
  }

  VV<int> calc() {
    rep(v, n) if (!vis[v]) dfs(v);

    fill(vis.begin(), vis.end(), false);

    int k = 0;
    reverse(vs.begin(), vs.end());

    VV<int> vcomp;

    for (int v : vs) {
      if (!vis[v]) {
        V<int> vec;
        rdfs(v, k++, vec);
        vcomp.push_back(vec);
      }
    }

    return vcomp;
  }
};

int main() {
  int N;
  cin >> N;
  V<int> a(N);
  rep(i, N) cin >> a[i], --a[i];

  SCC scc(N);
  rep(i, N) scc.add_edge(i, a[i]);
  auto comps = scc.calc();

  V<int> rev(N, -1);

  rep(i, N) {
    if (scc.cmp[i] != scc.cmp[a[i]]) {
      if (rev[a[i]] != -1) {
        cout << 0 << endl;
        return 0;
      }
      rev[a[i]] = i;
    }
  }

  V<int> cnt(N + 1);
  Mint ans(1);

  for (auto &comp : comps) { // cycles
    if (scc.cmp[comp[0]] != scc.cmp[a[comp[0]]])
      continue;
    int sz = comp.size();
    V<int> len(sz);

    int pos = -1;

    rep(i, sz) {
      int v = rev[comp[i]];
      int k = 0;
      while (v != -1) {
        k++;
        v = rev[v];
      }
      len[i] = k;
      if (k > 0) {
        pos = i;
      }
    }

    if (pos == -1) {
      cnt[sz]++;
    } else {
      rotate(comp.begin(), comp.begin() + pos, comp.end());
      rotate(len.begin(), len.begin() + pos, len.end());
      int lst = 0;

      per(i, sz) {
        if (len[i]) {
          int w = (lst - i + sz);
          if (w > sz)
            w -= sz;
          if (w > len[i]) {
            ans *= 2;
          } else if (w < len[i]) {
            ans = 0;
          }
          lst = i;
        }
      }
    }

    debug(comp, len);
  }

  for (int l = 1; l <= N; ++l) {
    if (cnt[l] == 0)
      continue;
    if (l & 1) {
      V<Mint> dp_odd(cnt[l] + 1);
      dp_odd[0] = 1;
      for (int i = 1; i <= cnt[l]; ++i) {
        if (l > 1) {
          dp_odd[i] = dp_odd[i - 1] * 2;
        } else {
          dp_odd[i] = dp_odd[i - 1];
        }
        if (i >= 2) {
          dp_odd[i] += dp_odd[i - 2] * (i - 1) * l;
        }
      }
      ans *= dp_odd[cnt[l]];
    } else {
      V<Mint> dp_even(cnt[l] + 1);
      dp_even[0] = 1;
      for (int i = 1; i <= N; ++i) {
        dp_even[i] = dp_even[i - 1];
        if (i >= 2) {
          dp_even[i] += dp_even[i - 2] * (i - 1) * l;
        }
      }
      ans *= dp_even[cnt[l]];
    }
  }

  cout << ans << endl;

  return 0;
}

Fixed submission:
#include <bits/stdc++.h>
using namespace std;

using ll = long long;
using pii = pair<int, int>;
template <class T> using V = vector<T>;
template <class T> using VV = V<V<T>>;

#define pb push_back
#define eb emplace_back
#define mp make_pair
#define fi first
#define se second
#define rep(i, n) rep2(i, 0, n)
#define rep2(i, m, n) for (int i = m; i < (n); i++)
#define per(i, b) per2(i, 0, b)
#define per2(i, a, b) for (int i = int(b) - 1; i >= int(a); i--)
#define ALL(c) (c).begin(), (c).end()
#define SZ(x) ((int)(x).size())

constexpr ll TEN(int n) { return (n == 0) ? 1 : 10 * TEN(n - 1); }

template <class T, class U> void chmin(T &t, const U &u) {
  if (t > u)
    t = u;
}
template <class T, class U> void chmax(T &t, const U &u) {
  if (t < u)
    t = u;
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  os << "(" << p.first << "," << p.second << ")";
  return os;
}

template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
  os << "{";
  rep(i, v.size()) {
    if (i)
      os << ",";
    os << v[i];
  }
  os << "}";
  return os;
}

#ifdef LOCAL
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 << __LINE__ << " [" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#define dump(x) cerr << __LINE__ << " " << #x << " = " << (x) << endl
#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif

template <unsigned int MOD> struct ModInt {
  using uint = unsigned int;
  using ull = unsigned long long;
  using M = ModInt;

  uint v;

  ModInt(ll _v = 0) { set_norm(_v % MOD + MOD); }
  M &set_norm(uint _v) { //[0, MOD * 2)->[0, MOD)
    v = (_v < MOD) ? _v : _v - MOD;
    return *this;
  }

  explicit operator bool() const { return v != 0; }
  M operator+(const M &a) const { return M().set_norm(v + a.v); }
  M operator-(const M &a) const { return M().set_norm(v + MOD - a.v); }
  M operator*(const M &a) const { return M().set_norm(ull(v) * a.v % MOD); }
  M operator/(const M &a) const { return *this * a.inv(); }
  M &operator+=(const M &a) { return *this = *this + a; }
  M &operator-=(const M &a) { return *this = *this - a; }
  M &operator*=(const M &a) { return *this = *this * a; }
  M &operator/=(const M &a) { return *this = *this / a; }
  M operator-() const { return M() - *this; }
  M &operator++(int) { return *this = *this + 1; }
  M &operator--(int) { return *this = *this - 1; }

  M pow(ll n) const {
    if (n < 0)
      return inv().pow(-n);
    M x = *this, res = 1;
    while (n) {
      if (n & 1)
        res *= x;
      x *= x;
      n >>= 1;
    }
    return res;
  }

  M inv() const {
    ll a = v, b = MOD, p = 1, q = 0, t;
    while (b != 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(p -= t * q, q);
    }
    return M(p);
  }

  bool operator==(const M &a) const { return v == a.v; }
  bool operator!=(const M &a) const { return v != a.v; }
  friend ostream &operator<<(ostream &os, const M &a) { return os << a.v; }
  static uint get_mod() { return MOD; }
};

using Mint = ModInt<1000000007>;

struct SCC {
  int n;
  VV<int> g, rg;
  V<int> vs, cmp;
  V<bool> vis;

  SCC() {}
  SCC(int n) : n(n) {
    g = rg = VV<int>(n);
    vs = cmp = V<int>(n);
    vis = V<bool>(n);
  }

  void add_edge(int from, int to) {
    g[from].push_back(to);
    rg[to].push_back(from);
  }

  void dfs(int v) {
    vis[v] = true;

    for (int to : g[v]) {
      if (!vis[to]) {
        dfs(to);
      }
    }

    vs.push_back(v);
  }

  void rdfs(int v, int k, V<int> &vec) {
    vis[v] = true;
    cmp[v] = k;
    vec.push_back(v);

    for (int to : rg[v]) {
      if (!vis[to]) {
        rdfs(to, k, vec);
      }
    }
  }

  VV<int> calc() {
    rep(v, n) if (!vis[v]) dfs(v);

    fill(vis.begin(), vis.end(), false);

    int k = 0;
    reverse(vs.begin(), vs.end());

    VV<int> vcomp;

    for (int v : vs) {
      if (!vis[v]) {
        V<int> vec;
        rdfs(v, k++, vec);
        vcomp.push_back(vec);
      }
    }

    return vcomp;
  }
};

int main() {
  int N;
  cin >> N;
  V<int> a(N);
  rep(i, N) cin >> a[i], --a[i];

  SCC scc(N);
  rep(i, N) scc.add_edge(i, a[i]);
  auto comps = scc.calc();

  V<int> rev(N, -1);

  rep(i, N) {
    if (scc.cmp[i] != scc.cmp[a[i]]) {
      if (rev[a[i]] != -1) {
        cout << 0 << endl;
        return 0;
      }
      rev[a[i]] = i;
    }
  }

  V<int> cnt(N + 1);
  Mint ans(1);

  for (auto &comp : comps) { // cycles
    if (scc.cmp[comp[0]] != scc.cmp[a[comp[0]]])
      continue;
    int sz = comp.size();
    V<int> len(sz);

    int pos = -1;

    rep(i, sz) {
      int v = rev[comp[i]];
      int k = 0;
      while (v != -1) {
        k++;
        v = rev[v];
      }
      len[i] = k;
      if (k > 0) {
        pos = i;
      }
    }

    if (pos == -1) {
      cnt[sz]++;
    } else {
      rotate(comp.begin(), comp.begin() + pos, comp.end());
      rotate(len.begin(), len.begin() + pos, len.end());
      int lst = 0;

      per(i, sz) {
        if (len[i]) {
          int w = (lst - i + sz);
          if (w > sz)
            w -= sz;
          if (w > len[i]) {
            ans *= 2;
          } else if (w < len[i]) {
            ans = 0;
          }
          lst = i;
        }
      }
    }

    debug(comp, len);
  }

  for (int l = 1; l <= N; ++l) {
    if (cnt[l] == 0)
      continue;
    if (l & 1) {
      V<Mint> dp_odd(cnt[l] + 1);
      dp_odd[0] = 1;
      for (int i = 1; i <= cnt[l]; ++i) {
        if (l > 1) {
          dp_odd[i] = dp_odd[i - 1] * 2;
        } else {
          dp_odd[i] = dp_odd[i - 1];
        }
        if (i >= 2) {
          dp_odd[i] += dp_odd[i - 2] * (i - 1) * l;
        }
      }
      ans *= dp_odd[cnt[l]];
    } else {
      V<Mint> dp_even(cnt[l] + 1);
      dp_even[0] = 1;
      for (int i = 1; i <= cnt[l]; ++i) {
        dp_even[i] = dp_even[i - 1];
        if (i >= 2) {
          dp_even[i] += dp_even[i - 2] * (i - 1) * l;
        }
      }
      ans *= dp_even[cnt[l]];
    }
  }

  cout << ans << endl;

  return 0;
}