Problem p01723 (C++) — buggy submission, verdict: Memory Limit Exceeded

#include <iostream>
#include <vector>
#define llint long long
#define mod 1000000007

using namespace std;

llint N;
vector<int> G[205];
bool used[205];
llint root;

llint dp[205][205][205];

llint fact[205], fact_i[205];

llint pow(llint a, llint n) {
  if (n == 0)
    return 1;
  if (n % 2) {
    return ((a % mod) * (pow(a, n - 1) % mod)) % mod;
  } else {
    return pow((a * a) % mod, n / 2) % mod;
  }
}

void make_fact() {
  llint val = 1;
  fact[0] = 1;
  for (int i = 1; i < 205; i++) {
    val *= i;
    val %= mod;
    fact[i] = val;
  }
  for (int i = 0; i < 205; i++) {
    fact_i[i] = pow(fact[i], mod - 2);
  }
}

llint comb(llint n, llint k) {
  llint ret = 1;
  ret *= fact[n];
  ret *= fact_i[k], ret %= mod;
  ret *= fact_i[n - k], ret %= mod;
  return ret;
}

void merge(vector<llint> &v1, vector<llint> v2) {
  llint tmp[205];
  llint a = v1.size() - 1, b = v2.size() - 1;
  for (int i = 0; i <= a + b; i++)
    tmp[i] = 0;

  for (int i = 1; i <= a; i++) {
    for (int j = 1; j <= b; j++) {
      llint n = v1[i] * v2[j] % mod;
      for (int k = 0; k <= i + j; k++) {
        tmp[k] += dp[i][j][k] * n % mod;
        tmp[k] %= mod;
      }
    }
  }

  v1.clear();
  for (int i = 0; i <= a + b; i++)
    v1.push_back(tmp[i]);
}

vector<llint> dfs(int v) {
  vector<llint> ret;
  if (G[v].size() == 0) {
    ret.push_back(0);
    ret.push_back(1);
    return ret;
  }

  ret = dfs(G[v][0]);
  for (int i = 1; i < G[v].size(); i++) {
    merge(ret, dfs(G[v][i]));
  }
  ret.insert(ret.begin(), 0);
  return ret;
}

int main(void) {
  make_fact();

  cin >> N;
  int a, b;
  for (int i = 0; i < N - 1; i++) {
    cin >> a >> b;
    G[a].push_back(b);
    used[b] = true;
  }
  if (N == 1) {
    cout << 1 << endl;
    return 0;
  }

  for (int i = 0; i < N; i++) {
    if (!used[i]) {
      root = i;
      break;
    }
  }

  for (int i = 1; i <= N; i++) {
    for (int j = 1; j <= N; j++) {
      for (int k = 0; k <= min(i, j); k++) {
        dp[i][j][i + j - k] = comb(i, k) * comb(i + j - k, i) % mod;
        dp[i][j][i + j - k] %= mod;
      }
    }
  }

  vector<llint> avec = dfs(root);
  llint ans = 0;
  for (int i = 0; i < avec.size(); i++)
    ans += avec[i], ans %= mod;
  cout << ans << endl;
  return 0;
}


Error: MLE

Fixed submission:

#include <iostream>
#include <vector>
#define llint long long
#define mod 1000000007

using namespace std;

llint N;
vector<llint> G[205];
bool used[205];
llint root;

llint dp[205][205][205];
vector<llint> vec[205][205];

llint fact[205], fact_i[205];

llint pow(llint a, llint n) {
  if (n == 0)
    return 1;
  if (n % 2) {
    return ((a % mod) * (pow(a, n - 1) % mod)) % mod;
  } else {
    return pow((a * a) % mod, n / 2) % mod;
  }
}

void make_fact() {
  llint val = 1;
  fact[0] = 1;
  for (int i = 1; i < 205; i++) {
    val *= i;
    val %= mod;
    fact[i] = val;
  }
  for (int i = 0; i < 205; i++) {
    fact_i[i] = pow(fact[i], mod - 2);
  }
}

llint comb(llint n, llint k) {
  llint ret = 1;
  ret *= fact[n];
  ret *= fact_i[k], ret %= mod;
  ret *= fact_i[n - k], ret %= mod;
  return ret;
}

void merge(vector<llint> &v1, vector<llint> v2) {
  llint tmp[205];
  llint a = v1.size() - 1, b = v2.size() - 1;
  for (int i = 0; i <= a + b; i++)
    tmp[i] = 0;

  for (int i = 1; i <= a; i++) {
    for (int j = 1; j <= b; j++) {
      llint n = v1[i] * v2[j] % mod;
      for (int k = 0; k <= i + j; k++) {
        tmp[k] += vec[i][j][k] * n % mod;
        tmp[k] %= mod;
      }
    }
  }

  v1.clear();
  for (int i = 0; i <= a + b; i++)
    v1.push_back(tmp[i]);
}

vector<llint> dfs(int v) {
  vector<llint> ret;
  if (G[v].size() == 0) {
    ret.push_back(0);
    ret.push_back(1);
    return ret;
  }

  ret = dfs(G[v][0]);
  for (int i = 1; i < G[v].size(); i++) {
    merge(ret, dfs(G[v][i]));
  }
  ret.insert(ret.begin(), 0);
  return ret;
}

int main(void) {
  make_fact();

  cin >> N;
  int a, b;
  for (int i = 0; i < N - 1; i++) {
    cin >> a >> b;
    G[a].push_back(b);
    used[b] = true;
  }
  if (N == 1) {
    cout << 1 << endl;
    return 0;
  }

  for (int i = 0; i < N; i++) {
    if (!used[i]) {
      root = i;
      break;
    }
  }

  for (int i = 1; i <= N; i++) {
    for (int j = 1; j <= N; j++) {
      for (int k = 0; k <= min(i, j); k++) {
        dp[i][j][i + j - k] = comb(i, k) * comb(i + j - k, i) % mod;
        dp[i][j][i + j - k] %= mod;
      }
      for (int k = 0; k <= i + j; k++) {
        vec[i][j].push_back(dp[i][j][k]);
      }
    }
  }

  vector<llint> avec = dfs(root);
  llint ans = 0;
  for (int i = 0; i < avec.size(); i++)
    ans += avec[i], ans %= mod;
  cout << ans << endl;
  return 0;
}