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

// #pragma GCC optimize("Ofast")
// #pragma GCC target("avx")
// #undef LOCAL

#include <algorithm>

#include <array>

#include <bitset>

#include <cassert>

#include <complex>

#include <cstdio>

#include <cstring>

#include <iostream>

#include <map>

#include <numeric>

#include <queue>

#include <set>

#include <string>

#include <unordered_map>

#include <unordered_set>

#include <vector>

using namespace std;

using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
constexpr ll TEN(int n) { return (n == 0) ? 1 : 10 * TEN(n - 1); }
template <class T> using V = vector<T>;
template <class T> using VV = V<V<T>>;

struct Scanner {
  FILE *fp = nullptr;
  char line[(1 << 15) + 1];
  size_t st = 0, ed = 0;
  void reread() {
    memmove(line, line + st, ed - st);
    ed -= st;
    st = 0;
    ed += fread(line + ed, 1, (1 << 15) - ed, fp);
    line[ed] = '\\0';
  }
  bool succ() {
    while (true) {
      if (st == ed) {
        reread();
        if (st == ed)
          return false;
      }
      while (st != ed && isspace(line[st]))
        st++;
      if (st != ed)
        break;
    }
    if (ed - st <= 50)
      reread();
    return true;
  }
  template <class T, enable_if_t<is_same<T, string>::value, int> = 0>
  bool read_single(T &ref) {
    if (!succ())
      return false;
    while (true) {
      size_t sz = 0;
      while (st + sz < ed && !isspace(line[st + sz]))
        sz++;
      ref.append(line + st, sz);
      st += sz;
      if (!sz || st != ed)
        break;
      reread();
    }
    return true;
  }
  template <class T, enable_if_t<is_integral<T>::value, int> = 0>
  bool read_single(T &ref) {
    if (!succ())
      return false;
    bool neg = false;
    if (line[st] == '-') {
      neg = true;
      st++;
    }
    ref = T(0);
    while (isdigit(line[st])) {
      ref = 10 * ref + (line[st++] - '0');
    }
    if (neg)
      ref = -ref;
    return true;
  }
  template <class T> bool read_single(V<T> &ref) {
    for (auto &d : ref) {
      if (!read_single(d))
        return false;
    }
    return true;
  }
  void read() {}
  template <class H, class... T> void read(H &h, T &...t) {
    bool f = read_single(h);
    assert(f);
    read(t...);
  }
  Scanner(FILE *_fp) : fp(_fp) {}
};

struct Printer {
public:
  template <bool F = false> void write() {}
  template <bool F = false, class H, class... T>
  void write(const H &h, const T &...t) {
    if (F)
      write_single(' ');
    write_single(h);
    write<true>(t...);
  }
  template <class... T> void writeln(const T &...t) {
    write(t...);
    write_single('\\n');
  }

  Printer(FILE *_fp) : fp(_fp) {}
  ~Printer() { flush(); }

private:
  static constexpr size_t SIZE = 1 << 15;
  FILE *fp;
  char line[SIZE], small[50];
  size_t pos = 0;
  void flush() {
    fwrite(line, 1, pos, fp);
    pos = 0;
  }
  void write_single(const char &val) {
    if (pos == SIZE)
      flush();
    line[pos++] = val;
  }
  template <class T, enable_if_t<is_integral<T>::value, int> = 0>
  void write_single(T val) {
    if (pos > (1 << 15) - 50)
      flush();
    if (val == 0) {
      write_single('0');
      return;
    }
    if (val < 0) {
      write_single('-');
      val = -val; // todo min
    }
    size_t len = 0;
    while (val) {
      small[len++] = char('0' + (val % 10));
      val /= 10;
    }
    for (size_t i = 0; i < len; i++) {
      line[pos + i] = small[len - 1 - i];
    }
    pos += len;
  }
  void write_single(const string &s) {
    for (char c : s)
      write_single(c);
  }
  void write_single(const char *s) {
    size_t len = strlen(s);
    for (size_t i = 0; i < len; i++)
      write_single(s[i]);
  }
  template <class T> void write_single(const V<T> &val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
      if (i)
        write_single(' ');
      write_single(val[i]);
    }
  }
};

template <uint MD> struct ModInt {
  using M = ModInt;
  static constexpr uint get_mod() { return MD; }
  const static M G;
  uint v;
  ModInt(ll _v = 0) { set_v(uint(_v % MD + MD)); }
  M &set_v(uint _v) {
    v = (_v < MD) ? _v : _v - MD;
    return *this;
  }
  explicit operator bool() const { return v != 0; }
  M operator-() const { return M() - *this; }
  M operator+(const M &r) const { return M().set_v(v + r.v); }
  M operator-(const M &r) const { return M().set_v(v + MD - r.v); }
  M operator*(const M &r) const { return M().set_v(uint(ull(v) * r.v % MD)); }
  M operator/(const M &r) const { return *this * r.inv(); }
  M &operator+=(const M &r) { return *this = *this + r; }
  M &operator-=(const M &r) { return *this = *this - r; }
  M &operator*=(const M &r) { return *this = *this * r; }
  M &operator/=(const M &r) { return *this = *this / r; }
  bool operator==(const M &r) const { return v == r.v; }
  M pow(ll n) const {
    M x = *this, r = 1;
    while (n) {
      if (n & 1)
        r *= x;
      x *= x;
      n >>= 1;
    }
    return r;
  }
  M inv() const { return pow(MD - 2); }
  friend ostream &operator<<(ostream &os, const M &r) { return os << r.v; }
};
// using Mint = ModInt<998244353>;
// template<> const Mint Mint::G = Mint(3);

using Mint = ModInt<998244353>;

Scanner sc = Scanner(stdin);
Printer pr = Printer(stdout);

VV<int> g;

int mdp, mv;
void dfs(int p, int b, int ndp = 0) {
  if (mdp <= ndp) {
    mdp = ndp;
    mv = p;
  }
  for (int d : g[p]) {
    if (d == b)
      continue;
    dfs(d, p, ndp + 1);
  }
}

V<int> path;
bool dfs_path(int p, int b, int t) {
  if (p == t) {
    path.push_back(p);
    return true;
  }
  for (int d : g[p]) {
    if (d == b)
      continue;
    if (dfs_path(d, p, t)) {
      path.push_back(p);
      return true;
    }
  }
  return false;
}

int U;

using P = array<Mint, 3>;

P solve(int p, int b, int ndps = 0) {
  if (g[p].size() == 1) {
    // leaf
    if (ndps == U) {
      // rad
      return {Mint(2), Mint(1), Mint(0)};
    } else {
      //            dbg(p, b, P{Mint(3), Mint(0)});
      return {Mint(3), Mint(0), Mint(0)};
    }
  }
  P dp = {Mint(1), Mint(0), Mint(0)};
  for (auto d : g[p]) {
    if (d == b)
      continue;
    auto ch = solve(d, p, ndps + 1);
    P ndp = {Mint(0), Mint(0), Mint(0)};
    for (int a = 0; a < 3; a++) {
      for (int b = 0; b < 3; b++) {
        ndp[min(2, a + b)] += dp[a] * ch[b];
      }
    }
    dp = ndp;
  }
  dp[0] = dp[0] * Mint(3) + (dp[1] + dp[2]) * Mint(2);
  return dp;
}

int main() {
  int n;
  sc.read(n);
  g = VV<int>(n);
  for (int i = 0; i < n - 1; i++) {
    int a, b;
    sc.read(a, b);
    a--;
    b--;
    g[a].push_back(b);
    g[b].push_back(a);
  }
  dfs(0, -1);
  int u = mv;
  dfs(mv, -1);
  int v = mv;
  dfs_path(u, -1, v);

  int L = int(path.size());
  if (L % 2) {
    U = (L / 2) - 1;
    int mid = path[L / 2];
    ;
    V<Mint> dp(4);
    dp[0] = Mint(1);
    for (int d : g[mid]) {
      V<Mint> ndp(4);
      auto x = solve(d, mid);
      Mint x0 = x[0] - (x[1] + x[2]), x1 = x[1];
      ndp[3] = dp[3] * x0 + dp[2] * x1 + dp[1] * x1;
      ndp[2] = dp[2] * x0 + dp[0] * x1;
      ndp[1] = dp[1] * x0 + dp[0] * x1;
      ndp[0] = dp[0] * x0;
      dp = ndp;
    };
    pr.writeln((dp[3] / Mint(2)).v);
  } else {
    int mid0 = path[L / 2 - 1], mid1 = path[L / 2];
    U = (L / 2 - 1);
    auto x = solve(mid0, mid1);
    auto y = solve(mid1, mid0);
    pr.writeln((x[1] * y[1]).v);
  }
  return 0;
}


Error: 0

Fixed submission:

// #pragma GCC optimize("Ofast")
// #pragma GCC target("avx")
// #undef LOCAL

#include <algorithm>

#include <array>

#include <bitset>

#include <cassert>

#include <complex>

#include <cstdio>

#include <cstring>

#include <iostream>

#include <map>

#include <numeric>

#include <queue>

#include <set>

#include <string>

#include <unordered_map>

#include <unordered_set>

#include <vector>

using namespace std;

using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
constexpr ll TEN(int n) { return (n == 0) ? 1 : 10 * TEN(n - 1); }
template <class T> using V = vector<T>;
template <class T> using VV = V<V<T>>;

struct Scanner {
  FILE *fp = nullptr;
  char line[(1 << 15) + 1];
  size_t st = 0, ed = 0;
  void reread() {
    memmove(line, line + st, ed - st);
    ed -= st;
    st = 0;
    ed += fread(line + ed, 1, (1 << 15) - ed, fp);
    line[ed] = '\\0';
  }
  bool succ() {
    while (true) {
      if (st == ed) {
        reread();
        if (st == ed)
          return false;
      }
      while (st != ed && isspace(line[st]))
        st++;
      if (st != ed)
        break;
    }
    if (ed - st <= 50)
      reread();
    return true;
  }
  template <class T, enable_if_t<is_same<T, string>::value, int> = 0>
  bool read_single(T &ref) {
    if (!succ())
      return false;
    while (true) {
      size_t sz = 0;
      while (st + sz < ed && !isspace(line[st + sz]))
        sz++;
      ref.append(line + st, sz);
      st += sz;
      if (!sz || st != ed)
        break;
      reread();
    }
    return true;
  }
  template <class T, enable_if_t<is_integral<T>::value, int> = 0>
  bool read_single(T &ref) {
    if (!succ())
      return false;
    bool neg = false;
    if (line[st] == '-') {
      neg = true;
      st++;
    }
    ref = T(0);
    while (isdigit(line[st])) {
      ref = 10 * ref + (line[st++] - '0');
    }
    if (neg)
      ref = -ref;
    return true;
  }
  template <class T> bool read_single(V<T> &ref) {
    for (auto &d : ref) {
      if (!read_single(d))
        return false;
    }
    return true;
  }
  void read() {}
  template <class H, class... T> void read(H &h, T &...t) {
    bool f = read_single(h);
    assert(f);
    read(t...);
  }
  Scanner(FILE *_fp) : fp(_fp) {}
};

struct Printer {
public:
  template <bool F = false> void write() {}
  template <bool F = false, class H, class... T>
  void write(const H &h, const T &...t) {
    if (F)
      write_single(' ');
    write_single(h);
    write<true>(t...);
  }
  template <class... T> void writeln(const T &...t) {
    write(t...);
    write_single('\\n');
  }

  Printer(FILE *_fp) : fp(_fp) {}
  ~Printer() { flush(); }

private:
  static constexpr size_t SIZE = 1 << 15;
  FILE *fp;
  char line[SIZE], small[50];
  size_t pos = 0;
  void flush() {
    fwrite(line, 1, pos, fp);
    pos = 0;
  }
  void write_single(const char &val) {
    if (pos == SIZE)
      flush();
    line[pos++] = val;
  }
  template <class T, enable_if_t<is_integral<T>::value, int> = 0>
  void write_single(T val) {
    if (pos > (1 << 15) - 50)
      flush();
    if (val == 0) {
      write_single('0');
      return;
    }
    if (val < 0) {
      write_single('-');
      val = -val; // todo min
    }
    size_t len = 0;
    while (val) {
      small[len++] = char('0' + (val % 10));
      val /= 10;
    }
    for (size_t i = 0; i < len; i++) {
      line[pos + i] = small[len - 1 - i];
    }
    pos += len;
  }
  void write_single(const string &s) {
    for (char c : s)
      write_single(c);
  }
  void write_single(const char *s) {
    size_t len = strlen(s);
    for (size_t i = 0; i < len; i++)
      write_single(s[i]);
  }
  template <class T> void write_single(const V<T> &val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
      if (i)
        write_single(' ');
      write_single(val[i]);
    }
  }
};

template <uint MD> struct ModInt {
  using M = ModInt;
  static constexpr uint get_mod() { return MD; }
  const static M G;
  uint v;
  ModInt(ll _v = 0) { set_v(uint(_v % MD + MD)); }
  M &set_v(uint _v) {
    v = (_v < MD) ? _v : _v - MD;
    return *this;
  }
  explicit operator bool() const { return v != 0; }
  M operator-() const { return M() - *this; }
  M operator+(const M &r) const { return M().set_v(v + r.v); }
  M operator-(const M &r) const { return M().set_v(v + MD - r.v); }
  M operator*(const M &r) const { return M().set_v(uint(ull(v) * r.v % MD)); }
  M operator/(const M &r) const { return *this * r.inv(); }
  M &operator+=(const M &r) { return *this = *this + r; }
  M &operator-=(const M &r) { return *this = *this - r; }
  M &operator*=(const M &r) { return *this = *this * r; }
  M &operator/=(const M &r) { return *this = *this / r; }
  bool operator==(const M &r) const { return v == r.v; }
  M pow(ll n) const {
    M x = *this, r = 1;
    while (n) {
      if (n & 1)
        r *= x;
      x *= x;
      n >>= 1;
    }
    return r;
  }
  M inv() const { return pow(MD - 2); }
  friend ostream &operator<<(ostream &os, const M &r) { return os << r.v; }
};
// using Mint = ModInt<998244353>;
// template<> const Mint Mint::G = Mint(3);

using Mint = ModInt<998244353>;

Scanner sc = Scanner(stdin);
Printer pr = Printer(stdout);

VV<int> g;

int mdp, mv;
void dfs(int p, int b, int ndp = 0) {
  if (mdp <= ndp) {
    mdp = ndp;
    mv = p;
  }
  for (int d : g[p]) {
    if (d == b)
      continue;
    dfs(d, p, ndp + 1);
  }
}

V<int> path;
bool dfs_path(int p, int b, int t) {
  if (p == t) {
    path.push_back(p);
    return true;
  }
  for (int d : g[p]) {
    if (d == b)
      continue;
    if (dfs_path(d, p, t)) {
      path.push_back(p);
      return true;
    }
  }
  return false;
}

int U;

using P = array<Mint, 3>;

P solve(int p, int b, int ndps = 0) {
  if (g[p].size() == 1) {
    // leaf
    if (ndps == U) {
      // rad
      return {Mint(2), Mint(1), Mint(0)};
    } else {
      //            dbg(p, b, P{Mint(3), Mint(0)});
      return {Mint(3), Mint(0), Mint(0)};
    }
  }
  P dp = {Mint(1), Mint(0), Mint(0)};
  for (auto d : g[p]) {
    if (d == b)
      continue;
    auto ch = solve(d, p, ndps + 1);
    P ndp = {Mint(0), Mint(0), Mint(0)};
    for (int a = 0; a < 3; a++) {
      for (int b = 0; b < 3; b++) {
        ndp[min(2, a + b)] += dp[a] * ch[b];
      }
    }
    dp = ndp;
  }
  dp[0] = dp[0] * Mint(3) + (dp[1] + dp[2]) * Mint(2);
  return dp;
}

int main() {
  int n;
  sc.read(n);
  g = VV<int>(n);
  for (int i = 0; i < n - 1; i++) {
    int a, b;
    sc.read(a, b);
    a--;
    b--;
    g[a].push_back(b);
    g[b].push_back(a);
  }
  dfs(0, -1);
  int u = mv;
  dfs(mv, -1);
  int v = mv;
  dfs_path(u, -1, v);

  int L = int(path.size());
  if (L % 2) {
    U = (L / 2) - 1;
    int mid = path[L / 2];
    ;
    V<Mint> dp(4);
    dp[0] = Mint(1);
    for (int d : g[mid]) {
      V<Mint> ndp(4);
      auto x = solve(d, mid);
      Mint x0 = x[0], x1 = x[1];
      ndp[3] = dp[3] * x0 + dp[2] * x1 + dp[1] * x1;
      ndp[2] = dp[2] * x0 + dp[0] * x1;
      ndp[1] = dp[1] * x0 + dp[0] * x1;
      ndp[0] = dp[0] * x0;
      dp = ndp;
    };
    pr.writeln((dp[3] / Mint(2)).v);
  } else {
    int mid0 = path[L / 2 - 1], mid1 = path[L / 2];
    assert(false);
    U = (L / 2 - 1);
    auto x = solve(mid0, mid1);
    auto y = solve(mid1, mid0);
    pr.writeln((x[1] * y[1]).v);
  }
  return 0;
}