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

#include <algorithm>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <queue>
#include <set>
#include <stdio.h>
#include <string>
#include <vector>

// calculate x%m for x "properly" for all x
long long int mod(long long int x, long long int m);

// calculate inverse of x in mod m
// if there is inverse of x   : return (inverse of x)
// if there is no inverse of x: return 0
long long int mod_inverse(long long int x, long long int m);

// calculate inverse of x in mod m for PRIME m
long long int mod_inverse_Fermat(long long int x, long long int m);

// calculate x^n mod m
long long int fast_power(long long int x, long long int n, long long int m);

long long int euclid_extended(long long int a, long long int b,
                              long long int &x, long long int &y);

using ll = long long int;
using namespace std;

const long long int MOD = 1e9 + 7;

int make_rooted_tree(std::vector<std::vector<long long int>> &G,
                     std::vector<std::vector<long long int>> &G_rooted,
                     std::vector<long long int> &par, long long int N,
                     long long int root);

long long int fill_Ndes(std::vector<std::vector<long long int>> &G_rooted,
                        long long int N, std::vector<long long int> &Ndes,
                        long long int i);

long long int fill_dp(std::vector<std::vector<long long int>> &G_rooted,
                      std::vector<long long int> &Ndes, long long int N,
                      std::vector<long long int> &dp,
                      std::vector<long long int> &fact,
                      std::vector<long long int> &invfact, long long int i);

long long int remake_dp(std::vector<std::vector<long long int>> &G_rooted,
                        std::vector<long long int> &Ndes,
                        std::vector<long long int> &dp, long long int N,
                        long long int i_current);

int main() {
  ll N, tmp1, tmp2;
  cin >> N;
  vector<vector<ll>> G(N);

  for (ll i = 0; i < N - 1; i++) {
    cin >> tmp1 >> tmp2;
    G[tmp1 - 1].push_back(tmp2 - 1);
    G[tmp2 - 1].push_back(tmp1 - 1);
  }

  // make rooted tree
  vector<vector<ll>> G_rooted(N);
  vector<ll> par(N);
  make_rooted_tree(G, G_rooted, par, N, 0);

  /*cerr << "G_rooted:" << endl;
  for(ll i = 0; i < N; i++){
    cerr << i << ":" << endl;
    for(ll j = 0; j < G_rooted[i].size(); j++){
      cerr << i << " " << G_rooted[i][j] << endl;
    }
  }*/

  // count decendents
  vector<ll> Ndes(N);
  fill_Ndes(G_rooted, N, Ndes, 0);

  /*cerr << "Ndes:" << endl;
  for(ll i = 0; i < N; i++){
    cerr << i << " " << Ndes[i] << endl;
  }*/

  // prepare factorization table
  vector<ll> fact(2e5 + 1), invfact(2e5 + 1);
  fact[0] = 1;
  invfact[0] = 1;

  for (ll i = 1; i < 2e5 + 1; i++) {
    fact[i] = (i * fact[i - 1] + MOD) % MOD;
    invfact[i] = mod_inverse(fact[i], MOD);
  }

  /*cerr << "fact:" << endl;
  for(ll i = 0; i < 10; i++){
    cerr << fact[i] << " ";
  }cerr << endl;*/

  // solve problem
  vector<ll> dp(N);
  fill_dp(G_rooted, Ndes, N, dp, fact, invfact, 0);

  /*cerr << "dp after first fill:" << endl;
  for(ll i = 0; i < N; i++){
    cerr << i << " " << dp[i] << endl;
  }*/
  remake_dp(G_rooted, Ndes, dp, N, 0);

  cerr << "Answer:" << endl;
  for (ll i = 0; i < N; i++) {
    cout << dp[i] << endl;
  }

  return 0;
}

int make_rooted_tree(std::vector<std::vector<long long int>> &G,
                     std::vector<std::vector<long long int>> &G_rooted,
                     std::vector<long long int> &par, long long int N,
                     long long int root) {

  for (long long int i = 0; i < G[root].size(); i++) {
    if (G[root][i] != par[root]) {
      par[G[root][i]] = root;
      G_rooted[root].push_back(G[root][i]);
      make_rooted_tree(G, G_rooted, par, N, G[root][i]);
    }
  }

  return 0;
}

long long int fill_Ndes(std::vector<std::vector<long long int>> &G_rooted,
                        long long int N, std::vector<long long int> &Ndes,
                        long long int i) {

  if (G_rooted[i].size() == 0) {
    Ndes[i] = 0;
    return 0;
  } else {
    long long int ans = G_rooted[i].size();
    for (long long int j = 0; j < G_rooted[i].size(); j++) {
      ans += fill_Ndes(G_rooted, N, Ndes, G_rooted[i][j]);
    }

    Ndes[i] = ans;
    return ans;
  }
}

long long int fill_dp(std::vector<std::vector<long long int>> &G_rooted,
                      std::vector<long long int> &Ndes, long long int N,
                      std::vector<long long int> &dp,
                      std::vector<long long int> &fact,
                      std::vector<long long int> &invfact, long long int i) {
  if (G_rooted[i].size() == 0) {
    dp[i] = 1;
    return 1;
  } else {
    long long int ans = fact[Ndes[i]];
    // cerr << ans << endl;
    for (long long int j = 0; j < G_rooted[i].size(); j++) {
      ans *= invfact[Ndes[G_rooted[i][j]] + 1];
      ans = (ans + MOD) % MOD;
      // cerr << ans << endl;
      ans *= fill_dp(G_rooted, Ndes, N, dp, fact, invfact, G_rooted[i][j]);
      ans = (ans + MOD) % MOD;
      // cerr << ans << endl;
    }
    // ans *= (G_rooted[i].size()+1);
    // ans = (ans+MOD)%MOD;
    dp[i] = ans;
    return ans;
  }
}

long long int remake_dp(std::vector<std::vector<long long int>> &G_rooted,
                        std::vector<long long int> &Ndes,
                        std::vector<long long int> &dp, long long int N,
                        long long int i_current) {

  long long int tmp = 1;

  for (long long int i = 0; i < G_rooted[i_current].size(); i++) {
    tmp = (dp[i_current] * (Ndes[G_rooted[i_current][i]] + 1) + MOD) % MOD;
    tmp = (tmp * mod_inverse(N - Ndes[G_rooted[i_current][i]] - 1, MOD) + MOD) %
          MOD;
    dp[G_rooted[i_current][i]] = tmp;
    remake_dp(G_rooted, Ndes, dp, N, G_rooted[i_current][i]);
  }
  return 0;
}

long long int mod(long long int x, long long int m) {
  if (x > 0) {
    return x % m;
  } else if (x == 0) {
    return 0;
  } else if ((-x) % m == 0) {
    return 0;
  } else {
    return m - (-x) % m;
  }
}

long long int euclid_extended(long long int a, long long int b,
                              long long int &x, long long int &y) {
  long long int d = a;
  if (b != 0) {
    d = euclid_extended(b, a % b, y, x);
    y -= (a / b) * x;
  } else {
    x = 1;
    y = 0;
  }

  return d;
}

long long int mod_inverse(long long int x, long long int m) {
  long long int tmp, x_inv, gcd_xm;
  gcd_xm = euclid_extended(x, m, x_inv, tmp);
  // if the inverse is calculate properly
  if (gcd_xm == 1) {
    return mod(x_inv, m);
  } else {
    // std::cerr << "Error in mod_inverse: there is no inverse of x in mod m" <<
    // std::endl;
    return 0;
  }
}

long long int mod_inverse_Fermat(long long int x, long long int m) {
  return fast_power(x, m - 2, m);
}

long long int fast_power(long long int x, long long int n, long long int m) {
  long long int ans = 1;

  while (n > 0) {
    if (n & 1) {
      ans = ans * x;
      ans = mod(ans, m);
    }
    x = x * x;
    x = mod(x, m);
    n = n >> 1;
  }

  return ans;
}


Error: TLE

Fixed submission:

#include <algorithm>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <queue>
#include <set>
#include <stdio.h>
#include <string>
#include <vector>

// calculate x%m for x "properly" for all x
long long int mod(long long int x, long long int m);

// calculate inverse of x in mod m
// if there is inverse of x   : return (inverse of x)
// if there is no inverse of x: return 0
long long int mod_inverse(long long int x, long long int m);

// calculate inverse of x in mod m for PRIME m
long long int mod_inverse_Fermat(long long int x, long long int m);

// calculate x^n mod m
long long int fast_power(long long int x, long long int n, long long int m);

long long int euclid_extended(long long int a, long long int b,
                              long long int &x, long long int &y);

using ll = long long int;
using namespace std;

const long long int MOD = 1e9 + 7;

int make_rooted_tree(std::vector<std::vector<long long int>> &G,
                     std::vector<std::vector<long long int>> &G_rooted,
                     std::vector<long long int> &par, long long int N,
                     long long int root);
long long int fill_Ndes(std::vector<std::vector<long long int>> G_rooted,
                        long long int N, std::vector<long long int> &Ndes,
                        long long int i);

long long int fill_dp(std::vector<std::vector<long long int>> &G_rooted,
                      std::vector<long long int> &Ndes, long long int N,
                      std::vector<long long int> &dp,
                      std::vector<long long int> &fact,
                      std::vector<long long int> &invfact, long long int i);

long long int remake_dp(std::vector<std::vector<long long int>> &G_rooted,
                        std::vector<long long int> &Ndes,
                        std::vector<long long int> &dp, long long int N,
                        long long int i_current);

int main() {
  ll N, tmp1, tmp2;
  cin >> N;
  vector<vector<ll>> G(N);

  for (ll i = 0; i < N - 1; i++) {
    cin >> tmp1 >> tmp2;
    G[tmp1 - 1].push_back(tmp2 - 1);
    G[tmp2 - 1].push_back(tmp1 - 1);
  }

  // make rooted tree
  vector<vector<ll>> G_rooted(N);
  vector<ll> par(N);
  make_rooted_tree(G, G_rooted, par, N, 0);

  /*cerr << "G_rooted:" << endl;
  for(ll i = 0; i < N; i++){
    cerr << i << ":" << endl;
    for(ll j = 0; j < G_rooted[i].size(); j++){
      cerr << i << " " << G_rooted[i][j] << endl;
    }
  }*/

  // count decendents
  vector<ll> Ndes(N);
  fill_Ndes(G_rooted, N, Ndes, 0);

  /*cerr << "Ndes:" << endl;
  for(ll i = 0; i < N; i++){
    cerr << i << " " << Ndes[i] << endl;
  }*/

  // prepare factorization table
  vector<ll> fact(2e5 + 1), invfact(2e5 + 1);
  fact[0] = 1;
  invfact[0] = 1;

  for (ll i = 1; i < 2e5 + 1; i++) {
    fact[i] = (i * fact[i - 1] + MOD) % MOD;
    invfact[i] = mod_inverse(fact[i], MOD);
  }

  /*cerr << "fact:" << endl;
  for(ll i = 0; i < 10; i++){
    cerr << fact[i] << " ";
  }cerr << endl;*/

  // solve problem
  vector<ll> dp(N);
  fill_dp(G_rooted, Ndes, N, dp, fact, invfact, 0);

  /*cerr << "dp after first fill:" << endl;
  for(ll i = 0; i < N; i++){
    cerr << i << " " << dp[i] << endl;
  }*/
  remake_dp(G_rooted, Ndes, dp, N, 0);

  cerr << "Answer:" << endl;
  for (ll i = 0; i < N; i++) {
    cout << dp[i] << endl;
  }

  return 0;
}

int make_rooted_tree(std::vector<std::vector<long long int>> &G,
                     std::vector<std::vector<long long int>> &G_rooted,
                     std::vector<long long int> &par, long long int N,
                     long long int root) {

  for (long long int i = 0; i < G[root].size(); i++) {
    if (G[root][i] != par[root]) {
      par[G[root][i]] = root;
      G_rooted[root].push_back(G[root][i]);
      make_rooted_tree(G, G_rooted, par, N, G[root][i]);
    }
  }

  return 0;
}

long long int fill_Ndes(std::vector<std::vector<long long int>> G_rooted,
                        long long int N, std::vector<long long int> &Ndes,
                        long long int i) {

  if (G_rooted[i].size() == 0) {
    Ndes[i] = 0;
    return 0;
  } else {
    long long int ans = G_rooted[i].size();
    for (long long int j = 0; j < G_rooted[i].size(); j++) {
      ans += fill_Ndes(G_rooted, N, Ndes, G_rooted[i][j]);
    }

    Ndes[i] = ans;
    return ans;
  }
}

long long int fill_dp(std::vector<std::vector<long long int>> &G_rooted,
                      std::vector<long long int> &Ndes, long long int N,
                      std::vector<long long int> &dp,
                      std::vector<long long int> &fact,
                      std::vector<long long int> &invfact, long long int i) {
  if (G_rooted[i].size() == 0) {
    dp[i] = 1;
    return 1;
  } else {
    long long int ans = fact[Ndes[i]];
    // cerr << ans << endl;
    for (long long int j = 0; j < G_rooted[i].size(); j++) {
      ans *= invfact[Ndes[G_rooted[i][j]] + 1];
      ans = (ans + MOD) % MOD;
      // cerr << ans << endl;
      ans *= fill_dp(G_rooted, Ndes, N, dp, fact, invfact, G_rooted[i][j]);
      ans = (ans + MOD) % MOD;
      // cerr << ans << endl;
    }
    // ans *= (G_rooted[i].size()+1);
    // ans = (ans+MOD)%MOD;
    dp[i] = ans;
    return ans;
  }
}

long long int remake_dp(std::vector<std::vector<long long int>> &G_rooted,
                        std::vector<long long int> &Ndes,
                        std::vector<long long int> &dp, long long int N,
                        long long int i_current) {

  long long int tmp = 1;

  for (long long int i = 0; i < G_rooted[i_current].size(); i++) {
    tmp = (dp[i_current] * (Ndes[G_rooted[i_current][i]] + 1) + MOD) % MOD;
    tmp = (tmp * mod_inverse(N - Ndes[G_rooted[i_current][i]] - 1, MOD) + MOD) %
          MOD;
    dp[G_rooted[i_current][i]] = tmp;
    remake_dp(G_rooted, Ndes, dp, N, G_rooted[i_current][i]);
  }
  return 0;
}

long long int mod(long long int x, long long int m) {
  if (x > 0) {
    return x % m;
  } else if (x == 0) {
    return 0;
  } else if ((-x) % m == 0) {
    return 0;
  } else {
    return m - (-x) % m;
  }
}

long long int euclid_extended(long long int a, long long int b,
                              long long int &x, long long int &y) {
  long long int d = a;
  if (b != 0) {
    d = euclid_extended(b, a % b, y, x);
    y -= (a / b) * x;
  } else {
    x = 1;
    y = 0;
  }

  return d;
}

long long int mod_inverse(long long int x, long long int m) {
  long long int tmp, x_inv, gcd_xm;
  gcd_xm = euclid_extended(x, m, x_inv, tmp);
  // if the inverse is calculate properly
  if (gcd_xm == 1) {
    return mod(x_inv, m);
  } else {
    // std::cerr << "Error in mod_inverse: there is no inverse of x in mod m" <<
    // std::endl;
    return 0;
  }
}

long long int mod_inverse_Fermat(long long int x, long long int m) {
  return fast_power(x, m - 2, m);
}

long long int fast_power(long long int x, long long int n, long long int m) {
  long long int ans = 1;

  while (n > 0) {
    if (n & 1) {
      ans = ans * x;
      ans = mod(ans, m);
    }
    x = x * x;
    x = mod(x, m);
    n = n >> 1;
  }

  return ans;
}