Problem p02728 (C++) — buggy submission, verdict: Runtime Error

#include <bits/stdc++.h>
#include <iostream>
#include <stack>
#include <vector>
using namespace std;
#define MOD 1000000007

typedef long long ll;

vector<ll> fac, finv, inv;
void COMinit(int n) {
  fac.resize(n + 1);
  finv.resize(n + 1);
  inv.resize(n + 1);
  fac.at(0) = fac.at(1) = 1;
  finv.at(0) = finv.at(1) = 1;
  inv.at(1) = 1;
  for (int i = 2; i <= n; i++) {
    fac.at(i) = fac.at(i - 1) * i % MOD;
    inv.at(i) = MOD - inv.at(MOD % i) * (MOD / i) % MOD;
    finv.at(i) = finv.at(i - 1) * inv.at(i) % MOD;
  }
}
ll COM(int n, int k) {
  if (n < k)
    return 0;
  if (n < 0 || k < 0)
    return 0;
  // cout << "fac(n):" << fac.at(n) << " finv(k):" << finv.at(k) << "
  // finv(n-k):" << finv.at(n-k) << endl;
  return fac.at(n) * (finv.at(k) * finv.at(n - k) % MOD) % MOD;
}

typedef struct {
  int size;
  ll val;
} SubTree;

SubTree merge(SubTree s1, SubTree s2) {
  int size;
  ll val;

  size = s1.size + s2.size;
  val = (s1.val * s2.val) % MOD;
  val = (val * COM(size, s1.size)) % MOD;
  // cout << "merge s1(" << s1.size << "," << s1.val << ")+s2(" << s2.size <<
  // "," << s2.val << ")->new(" << size << "," << val << ")" << endl;

  return SubTree{size, val};
}

SubTree addNode(SubTree s, int node) {
  int size;
  ll val;

  size = s.size + 1;
  val = s.val;
  // cout << "addnode node:" << node << " size:" << size << " val:" << val <<
  // endl;

  return SubTree{size, val};
}

int main(int, char **) {
  int nodeCount;
  cin >> nodeCount;

  COMinit(nodeCount);

  vector<vector<int>> adjacents(nodeCount + 1);
  vector<vector<int>> indexForAdjacents(nodeCount + 1);

  // 隣接ノードの記録
  for (int i = 0; i < nodeCount - 1; i++) {
    int a, b;
    cin >> a >> b;
    indexForAdjacents.at(a).push_back(adjacents.at(b).size());
    indexForAdjacents.at(b).push_back(adjacents.at(a).size());
    adjacents.at(a).push_back(b);
    adjacents.at(b).push_back(a);
  }

  vector<vector<SubTree>> childSubTreeRes(nodeCount + 1);
  for (int i = 0; i < nodeCount + 1; i++)
    childSubTreeRes.at(i).resize(adjacents.at(i).size());
  vector<ll> nodeRes(nodeCount + 1);
  vector<int> order;
  vector<int> parents(nodeCount + 1);
  SubTree Identity = {0, 1};

  // 行きがけ順と親ノードの記録
  stack<int> stack;
  stack.push(1);
  while (!stack.empty()) {
    int node = stack.top();
    stack.pop();

    order.push_back(node);
    for (int n : adjacents.at(node)) {
      if (n == parents.at(node))
        continue;
      stack.push(n);
      parents.at(n) = node;
    }
  }

  // 根=1の場合の情報を取得
  // cout << "1-root" << endl;
  for (int i = order.size() - 1; i >= 1; i--) {
    int node = order.at(i);
    int parent = parents.at(node);
    int parentIndex = -1;
    SubTree result = Identity;

    for (int j = 0; j < adjacents.at(node).size(); j++) {
      // cout << "node:" << node << " parent:" << parent << " nowcheck:" <<
      // adjacents.at(node).at(j) << endl;
      if (adjacents.at(node).at(j) == parent) {
        parentIndex = j;
        continue;
      }
      result = merge(result, childSubTreeRes.at(node).at(j));
    }
    childSubTreeRes.at(parent).at(indexForAdjacents.at(node).at(parentIndex)) =
        addNode(result, node);
    // cout << "childTreeRes save (" << parent << "," <<
    // indexForAdjacents.at(node).at(parentIndex) << ")<-(" << result.size+1 <<
    // "," << result.val << ")" << endl;
  }

  // cout << endl << "all-root" << endl;
  //  根が任意の場合の結果を算出
  for (int i = 0; i < order.size(); i++) {
    int node = order.at(i);
    int adjsize = adjacents.at(node).size();
    // 後方累積用の配列
    vector<SubTree> accumFromTail(adjsize);
    accumFromTail.at(adjsize - 1) = Identity;
    for (int j = adjsize - 1; j >= 1; j--)
      accumFromTail.at(j - 1) =
          merge(childSubTreeRes.at(node).at(j), accumFromTail.at(j));
    // 前方累積用の変数
    SubTree accum = Identity;
    for (int j = 0; j < adjsize; j++) {
      // cout << "node:" << node << " nowcheck:" << adjacents.at(node).at(j) <<
      // endl;
      SubTree result = addNode(merge(accum, accumFromTail.at(j)), node);
      childSubTreeRes.at(adjacents.at(node).at(j))
          .at(indexForAdjacents.at(node).at(j)) = result;
      accum = merge(accum, childSubTreeRes.at(node).at(j));
    }
    nodeRes.at(node) = addNode(accum, node).val;
  }

  for (int i = 1; i <= nodeCount; i++)
    cout << nodeRes.at(i) << endl;

  return 0;
}


Error: 0

Fixed submission:

#include <iostream>
#include <stack>
#include <vector>
using namespace std;

vector<vector<long long int>> comb;
void makeComb(int n) {
  comb.resize(n + 1);
  for (int i = 0; i <= n; i++)
    comb.at(i).resize(n + 1);

  for (int i = 0; i <= n; i++) {
    comb.at(i).at(0) = 1;
    comb.at(i).at(i) = 1;
  }
  for (int i = 1; i <= n; i++)
    for (int j = 1; j < i; j++)
      comb.at(i).at(j) = comb.at(i - 1).at(j - 1) + comb.at(i - 1).at(j);
}

typedef struct {
  int size;
  int val;
} SubTree;

SubTree merge(SubTree s1, SubTree s2) {
  int size;
  int val;

  size = s1.size + s2.size;
  val = comb.at(size).at(s1.size) * s1.val * s2.val;
  //    cout << "merge s1(" << s1.size << "," << s1.val << ")+s2(" << s2.size <<
  //    "," << s2.val << ")->new(" << size << "," << val << ")" << endl;

  return SubTree{size, val};
}

SubTree addNode(SubTree s, int node) {
  int size;
  int val;

  size = s.size + 1;
  val = s.val;
  //    cout << "addnode node:" << node << " size:" << size << " val:" << val <<
  //    endl;

  return SubTree{size, val};
}

int main(void) {
  int nodeCount;
  cin >> nodeCount;

  makeComb(nodeCount);

  vector<vector<int>> adjacents(nodeCount + 1);
  vector<vector<int>> indexForAdjacents(nodeCount + 1);
  vector<vector<SubTree>> childSubTreeRes(nodeCount + 1,
                                          vector<SubTree>(nodeCount + 1));
  vector<int> nodeRes(nodeCount + 1);
  vector<int> order;
  vector<int> parents(nodeCount + 1);
  SubTree Identity = {0, 1};

  // 隣接ノードの記録
  for (int i = 0; i < nodeCount - 1; i++) {
    int a, b;
    cin >> a >> b;
    indexForAdjacents.at(a).push_back(adjacents.at(b).size());
    indexForAdjacents.at(b).push_back(adjacents.at(a).size());
    adjacents.at(a).push_back(b);
    adjacents.at(b).push_back(a);
  }

  // 行きがけ順と親ノードの記録
  stack<int> stack;
  stack.push(1);
  while (!stack.empty()) {
    int node = stack.top();
    stack.pop();

    order.push_back(node);
    for (int n : adjacents.at(node)) {
      if (n == parents.at(node))
        continue;
      stack.push(n);
      parents.at(n) = node;
    }
  }

  // 根=1の場合の情報を取得
  //    cout << "1-root" << endl;
  for (int i = order.size() - 1; i >= 1; i--) {
    int node = order.at(i);
    int parent = parents.at(node);
    int parentIndex = -1;
    SubTree result = Identity;

    for (int j = 0; j < adjacents.at(node).size(); j++) {
      //            cout << "node:" << node << " parent:" << parent << "
      //            nowcheck:" << adjacents.at(node).at(j) << endl;
      if (adjacents.at(node).at(j) == parent) {
        parentIndex = j;
        continue;
      }
      result = merge(result, childSubTreeRes.at(node).at(j));
    }
    childSubTreeRes.at(parent).at(indexForAdjacents.at(node).at(parentIndex)) =
        addNode(result, node);
    //        cout << "childTreeRes save (" << parent << "," <<
    //        indexForAdjacents.at(node).at(parentIndex) << ")<-(" <<
    //        result.size+1 << "," << result.val << ")" << endl;
  }

  //    cout << endl << "all-root" << endl;
  // 根が任意の場合の結果を算出
  for (int i = 0; i < order.size(); i++) {
    int node = order.at(i);
    int adjsize = adjacents.at(node).size();
    // 後方累積用の配列
    vector<SubTree> accumFromTail(adjsize);
    accumFromTail.at(adjsize - 1) = Identity;
    for (int j = adjsize - 1; j >= 1; j--)
      accumFromTail.at(j - 1) =
          merge(childSubTreeRes.at(node).at(j), accumFromTail.at(j));
    // 前方累積用の変数
    SubTree accum = Identity;
    for (int j = 0; j < adjsize; j++) {
      //            cout << "node:" << node << " nowcheck:" <<
      //            adjacents.at(node).at(j) << endl;
      SubTree result = addNode(merge(accum, accumFromTail.at(j)), node);
      childSubTreeRes.at(adjacents.at(node).at(j))
          .at(indexForAdjacents.at(node).at(j)) = result;
      accum = merge(accum, childSubTreeRes.at(node).at(j));
    }
    nodeRes.at(node) = addNode(accum, node).val;
  }

  for (int i = 1; i <= nodeCount; i++)
    cout << nodeRes.at(i) << endl;

  return 0;
}