Problem p02728 (C++) — buggy submission, verdict: Time Limit Exceeded

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

template <uint32_t mod> class modint {
  uint64_t value;

public:
  constexpr modint(const int64_t x = 0) noexcept
      : value(x % mod + (x < 0 ? mod : 0)) {}
  constexpr explicit operator uint64_t() const noexcept { return value; }
  constexpr modint inverse() const noexcept { return pow(*this, mod - 2); }
  constexpr bool operator==(const modint &rhs) const noexcept {
    return value == rhs.value;
  }
  constexpr bool operator!=(const modint &rhs) const noexcept {
    return value != rhs.value;
  }
  constexpr modint operator+() const noexcept { return modint(*this); }
  constexpr modint operator-() const noexcept { return modint(mod - value); }
  constexpr modint operator+(const modint &rhs) const noexcept {
    return modint(*this) += rhs;
  }
  constexpr modint operator-(const modint &rhs) const noexcept {
    return modint(*this) -= rhs;
  }
  constexpr modint operator*(const modint &rhs) const noexcept {
    return modint(*this) *= rhs;
  }
  constexpr modint operator/(const modint &rhs) const noexcept {
    return modint(*this) /= rhs;
  }
  constexpr modint &operator+=(const modint &rhs) noexcept {
    if ((value += rhs.value) >= mod)
      value -= mod;
    return *this;
  }
  constexpr modint &operator-=(const modint &rhs) noexcept {
    return *this += mod - rhs.value;
  }
  constexpr modint &operator*=(const modint &rhs) noexcept {
    if ((value *= rhs.value) >= mod)
      value %= mod;
    return *this;
  }
  constexpr modint &operator/=(const modint &rhs) noexcept {
    return *this *= rhs.inverse();
  }
  constexpr modint operator++(int) noexcept {
    modint ret(*this);
    if ((++value) >= mod)
      value -= mod;
    return ret;
  }
  constexpr modint operator--(int) noexcept {
    modint ret(*this);
    if ((value += mod - 1) >= mod)
      value -= mod;
    return ret;
  }
  constexpr modint &operator++() noexcept { return *this += 1; }
  constexpr modint &operator--() noexcept { return *this -= 1; }
  friend std::ostream &operator<<(std::ostream &os, const modint<mod> &x) {
    return os << x.value;
  }
  friend std::istream &operator>>(std::istream &is, modint<mod> &x) {
    int64_t i;
    is >> i;
    x = modint<mod>(i);
    return is;
  }
  friend constexpr modint<mod> pow(const modint<mod> &x, uint64_t y) {
    modint<mod> ret{1}, m{x};
    while (y > 0) {
      if (y & 1)
        ret *= m;
      m *= m;
      y >>= 1;
    }
    return ret;
  }
};
constexpr int64_t mod = 1000000007;

int n;
int parent[200000];
map<pair<int, int>, modint<mod>> edp, cnt;
modint<mod> vdp[200000], vmul[200000];
vector<int> edge[200000];
modint<mod> fact[200001], finv[200001];

int getcnt(int v, int p = -1) {
  int ch = 1;
  vdp[v] = 1;
  for (int c : edge[v]) {
    if (c == p)
      continue;
    int gc = getcnt(c, v);
    ch += gc;
    vdp[v] *= finv[gc];
  }
  if (p >= 0) {
    cnt[{p, v}] = ch;
    cnt[{v, p}] = n - ch;
    vdp[v] *= finv[n - ch];
  }
  return ch;
}
modint<mod> solve(int v, int p) {
  parent[v] = p;
  modint<mod> pans = 1;
  for (auto c : edge[v]) {
    if (c == p)
      continue;
    pans *= solve(c, v);
  }
  modint<mod> val = pans * fact[(uint64_t)cnt[{p, v}] - 1] * vdp[v] *
                    fact[(uint64_t)cnt[{v, p}]];
  vmul[p] *= val;
  return edp[{p, v}] = val;
}
void rsolve(int v, int p) {
  modint<mod> pans = vmul[p] / edp[{p, v}];
  modint<mod> val = pans * fact[(uint64_t)cnt[{v, p}] - 1] * vdp[p] *
                    fact[(uint64_t)cnt[{p, v}]];
  vmul[v] *= val;
  edp[{v, p}] = val;
  for (auto c : edge[v])
    if (c != p)
      rsolve(c, v);
}

int main() {
  cin.tie(nullptr);
  ios::sync_with_stdio(false);

  fact[0] = 1;
  for (int i = 1; i <= 200000; ++i)
    fact[i] = fact[i - 1] * i;
  finv[200000] = fact[200000].inverse();
  for (int i = 200000; i >= 1; --i)
    finv[i - 1] = finv[i] * i;

  cin >> n;
  for (int i = 1; i < n; ++i) {
    int a, b;
    cin >> a >> b;
    --a;
    --b;
    edge[a].emplace_back(b);
    edge[b].emplace_back(a);
  }

  getcnt(0);
  for (int k = 0; k < n; ++k)
    vmul[k] = 1;
  for (int v : edge[0])
    solve(v, 0);
  for (int v : edge[0])
    rsolve(v, 0);
  for (int k = 0; k < n; ++k)
    cout << fact[n - 1] * vdp[k] * vmul[k] << endl;

  return 0;
}

Error: TLE

Fixed submission:

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

template <uint32_t mod> class modint {
  uint64_t value;

public:
  constexpr modint(const int64_t x = 0) noexcept
      : value(x % mod + (x < 0 ? mod : 0)) {}
  constexpr explicit operator uint64_t() const noexcept { return value; }
  constexpr modint inverse() const noexcept { return pow(*this, mod - 2); }
  constexpr bool operator==(const modint &rhs) const noexcept {
    return value == rhs.value;
  }
  constexpr bool operator!=(const modint &rhs) const noexcept {
    return value != rhs.value;
  }
  constexpr modint operator+() const noexcept { return modint(*this); }
  constexpr modint operator-() const noexcept { return modint(mod - value); }
  constexpr modint operator+(const modint &rhs) const noexcept {
    return modint(*this) += rhs;
  }
  constexpr modint operator-(const modint &rhs) const noexcept {
    return modint(*this) -= rhs;
  }
  constexpr modint operator*(const modint &rhs) const noexcept {
    return modint(*this) *= rhs;
  }
  constexpr modint operator/(const modint &rhs) const noexcept {
    return modint(*this) /= rhs;
  }
  constexpr modint &operator+=(const modint &rhs) noexcept {
    if ((value += rhs.value) >= mod)
      value -= mod;
    return *this;
  }
  constexpr modint &operator-=(const modint &rhs) noexcept {
    return *this += mod - rhs.value;
  }
  constexpr modint &operator*=(const modint &rhs) noexcept {
    if ((value *= rhs.value) >= mod)
      value %= mod;
    return *this;
  }
  constexpr modint &operator/=(const modint &rhs) noexcept {
    return *this *= rhs.inverse();
  }
  constexpr modint operator++(int) noexcept {
    modint ret(*this);
    if ((++value) >= mod)
      value -= mod;
    return ret;
  }
  constexpr modint operator--(int) noexcept {
    modint ret(*this);
    if ((value += mod - 1) >= mod)
      value -= mod;
    return ret;
  }
  constexpr modint &operator++() noexcept { return *this += 1; }
  constexpr modint &operator--() noexcept { return *this -= 1; }
  friend std::ostream &operator<<(std::ostream &os, const modint<mod> &x) {
    return os << x.value;
  }
  friend std::istream &operator>>(std::istream &is, modint<mod> &x) {
    int64_t i;
    is >> i;
    x = modint<mod>(i);
    return is;
  }
  friend constexpr modint<mod> pow(const modint<mod> &x, uint64_t y) {
    modint<mod> ret{1}, m{x};
    while (y > 0) {
      if (y & 1)
        ret *= m;
      m *= m;
      y >>= 1;
    }
    return ret;
  }
};
constexpr int64_t mod = 1000000007;

int n;
map<pair<int, int>, modint<mod>> edp, cnt;
modint<mod> vdp[200000], v2[200000];
vector<int> edge[200000];
modint<mod> fact[200001], finv[200001];

int getcnt(int v, int p = -1) {
  int ch = 1;
  vdp[v] = 1;
  for (int c : edge[v]) {
    if (c == p)
      continue;
    int gc = getcnt(c, v);
    ch += gc;
    vdp[v] *= finv[gc];
  }
  if (p >= 0) {
    cnt[{p, v}] = ch;
    cnt[{v, p}] = n - ch;
    vdp[v] *= finv[n - ch];
  }
  return ch;
}
modint<mod> solve(int v, int p) {
  if (edp.count({p, v}))
    return edp[{p, v}];
  modint<mod> ans = 1;
  for (auto c : edge[v]) {
    if (c == p)
      continue;
    ans *= solve(c, v);
  }
  modint<mod> val = ans * fact[(uint64_t)cnt[{p, v}] - 1] * vdp[v] *
                    fact[(uint64_t)cnt[{v, p}]];
  v2[p] *= val;
  return edp[{p, v}] = val;
}

int main() {
  cin.tie(nullptr);
  ios::sync_with_stdio(false);

  fact[0] = 1;
  for (int i = 1; i <= 200000; ++i)
    fact[i] = fact[i - 1] * i;
  finv[200000] = fact[200000].inverse();
  for (int i = 200000; i >= 1; --i)
    finv[i - 1] = finv[i] * i;

  cin >> n;
  for (int i = 1; i < n; ++i) {
    int a, b;
    cin >> a >> b;
    --a;
    --b;
    edge[a].emplace_back(b);
    edge[b].emplace_back(a);
  }

  getcnt(0);
  for (int k = 0; k < n; ++k)
    v2[k] = 1;
  for (int k = 0; k < n; ++k) {
    for (int v : edge[k])
      solve(v, k);
  }
  for (int k = 0; k < n; ++k)
    cout << fact[n - 1] * vdp[k] * v2[k] << endl;
  return 0;
}