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

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

#ifndef DEBUG
#define endl '\\n'
#define debug(...)
#else
#define debug(...) __VA_ARGS__
#endif
#define debugf(...) debug(printf(__VA_ARGS__);)

const int N = 2e5 + 5;
using ll = long long;
constexpr ll mod = 1e9 + 7;

vector<int> g[N];
ll down[N];
int sz[N];

ll fac[N];

ll fexp(ll x, ll e) {
  ll ans = 1;
  for (; e > 0; e >>= 1) {
    if (e & 1)
      ans = ans * x % mod;
    x = x * x % mod;
  }
  return ans;
}

ll inv(ll x) { return fexp(x, mod - 2); }

ll C(ll n, ll k) {
  if (n - k < 0)
    return 0;
  return fac[n] * inv(fac[n - k] * fac[k] % mod) % mod;
}

void build(int u, int p = 0) {
  sz[u] = 1;
  for (int v : g[u])
    if (v != p) {
      build(v, u);
      sz[u] += sz[v];
    }
}

void go_subtree(int u, int p = 0) {
  // down[u] = product{ down[v], for every v child of u } * (sz[u] - 1)! /
  // product{ sz[v]!, for every v child of u }
  down[u] = fac[sz[u] - 1];
  ll k = 1;
  for (int v : g[u])
    if (v != p) {
      go_subtree(v, u);
      down[u] = down[u] * down[v] % mod;
      k *= fac[sz[v]];
      k %= mod;
    }

  down[u] = down[u] * inv(k) % mod;
  debugf("down[%d] = %lld\\n", u, down[u]);
}

void go_root(int u, int p = 0) {
  for (int v : g[u])
    if (v != p) {
      ll down_wo_v = down[u];
      down_wo_v *= inv(down[v]);
      down_wo_v %= mod;
      down_wo_v *= inv(fac[sz[u] - 1]);
      down_wo_v %= mod;
      down_wo_v *= fac[sz[v]];
      down_wo_v %= mod;
      down_wo_v *= fac[sz[u] - sz[v] - 1];
      down_wo_v %= mod;

      down[v] *= down_wo_v;
      down[v] %= mod;
      down[v] *= inv(fac[sz[v] - 1]);
      down[v] %= mod;
      down[v] *= fac[sz[u] - 1];
      down[v] %= mod;
      down[v] *= inv(fac[sz[u] - sz[v]]);
      down[v] %= mod;

      sz[v] = sz[u];
      go_root(v, u);
    }
}

int(((((main)))))() <%
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);

  fac[0] = 1;
  for (int i = 1; i < N; i++)
    fac[i] = fac[i - 1] * i % mod;

  int n;
  cin >> n;
  for (int i = 0; i < n - 1; i++) {
    int u, v;
    cin >> u >> v;
    g[u].emplace_back(v);
    g[v].emplace_back(u);
  }

  build(1);
  go_subtree(1);
  go_root(1);

  for (int i = 1; i <= n; i++)
    cout << down[i] << endl;

  return 0;
%>

Error: TLE

Fixed submission:

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

#ifndef DEBUG
#define endl '\\n'
#define debug(...)
#else
#define debug(...) __VA_ARGS__
#endif
#define debugf(...) debug(printf(__VA_ARGS__);)

const int N = 2e5 + 5;
using ll = long long;
constexpr ll mod = 1e9 + 7;

vector<int> g[N];
ll down[N], up[N];
ll ans[N];
int sz[N];

ll fac[N];

ll fexp(ll x, ll e) {
  ll ans = 1;
  for (; e > 0; e >>= 1) {
    if (e & 1)
      ans = ans * x % mod;
    x = x * x % mod;
  }
  return ans;
}

ll inv(ll x) { return fexp(x, mod - 2); }

ll C(ll n, ll k) {
  if (n - k < 0)
    return 0;
  return fac[n] * inv(fac[n - k] * fac[k] % mod) % mod;
}

void build(int u, int p = 0) {
  sz[u] = 1;
  for (int v : g[u])
    if (v != p) {
      build(v, u);
      sz[u] += sz[v];
    }
}

void go_subtree(int u, int p = 0) {
  // down[u] = product{ down[v], for every v child of u } * (sz[u] - 1)! /
  // product{ sz[v]!, for every v child of u }
  down[u] = fac[sz[u] - 1];
  ll k = 1;
  for (int v : g[u])
    if (v != p) {
      go_subtree(v, u);
      down[u] = down[u] * down[v] % mod;
      k *= fac[sz[v]];
    }

  down[u] = down[u] * inv(k) % mod;
  debugf("down[%d] = %lld\\n", u, down[u]);
}

void go_root(int u, int p = 0, int szUp = 0) {
  ans[u] = down[u];
  sz[u] += szUp;

  int pool = sz[1] - 1;
  for (int v : g[u])
    if (v != p) {
      // Will it work??
      down[v] *= down[u] * inv(C(pool, sz[v])) % mod;
      down[v] %= mod;
      down[v] *= C(pool, sz[u] - sz[v]);
      down[v] %= mod;
      go_root(v, u, sz[u] - sz[v]);
    }
}

int(((((main)))))() <%
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);

  fac[0] = 1;
  for (int i = 1; i < N; i++)
    fac[i] = fac[i - 1] * i % mod;

  int n;
  cin >> n;
  for (int i = 0; i < n - 1; i++) {
    int u, v;
    cin >> u >> v;
    g[u].emplace_back(v);
    g[v].emplace_back(u);
  }

  // build(1);
  // go_subtree(1);
  // go_root(1);

  for (int u = 1; u <= n; u++) {
    build(u);
    go_subtree(u);
    ans[u] = down[u];
  }

  for (int i = 1; i <= n; i++)
    cout << ans[i] << endl;

  return 0;
%>