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

#include <bits/stdc++.h>

#ifdef LOCAL
#include "dump.hpp"
#else
#define dump(...)
#endif

using namespace std;

struct fraction {
  typedef long long int_t;
  int_t nume, deno;

  static inline int_t gcd(int_t a, int_t b) { return __gcd(abs(a), abs(b)); }

  void reduce() {
    const int_t g = gcd(nume, deno);
    nume /= g;
    deno /= g;
  }

  fraction(int_t nume_ = 0, int_t deno_ = 1) : nume(nume_), deno(deno_) {
    reduce();
  }
  fraction(const fraction &f) : nume(f.nume), deno(f.deno) {}

  fraction &operator+=(const fraction &f) {
    const int_t r_deno = deno / gcd(deno, f.deno) * f.deno;
    nume = r_deno / deno * nume + r_deno / f.deno * f.nume;
    deno = r_deno;
    reduce();
    return *this;
  }

  fraction &operator-=(const fraction &f) {
    return *this += fraction(-f.nume, f.deno);
  }

  fraction &operator*=(const fraction &f) {
    const int_t g1 = gcd(nume, f.deno);
    const int_t g2 = gcd(f.nume, deno);
    nume = (nume / g1) * (f.nume / g2);
    deno = (deno / g2) * (f.deno / g1);
    return *this;
  }

  fraction &operator/=(const fraction &f) {
    return *this *= fraction(f.deno, f.nume);
  }

  fraction operator+(const fraction &f) const { return fraction(*this) += f; }

  fraction operator-(const fraction &f) const { return fraction(*this) -= f; }

  fraction operator*(const fraction &f) const { return fraction(*this) *= f; }

  fraction operator/(const fraction &f) const { return fraction(*this) /= f; }

  bool operator==(const fraction &f) const {
    return nume == f.nume && deno == f.deno;
  }

  bool operator<(const fraction &f) const {
    const int_t lcm_deno = deno / gcd(deno, f.deno) * f.deno;
    return lcm_deno / deno * nume < lcm_deno / f.deno * f.nume;
  }

  string to_string() const {
    return std::to_string(nume) + "/" + std::to_string(deno);
  }

  double to_double() const { return (double)nume / deno; }

  long double to_long_double() const { return (long double)nume / deno; }
};

inline ostream &operator<<(ostream &os, const fraction &f) {
  return os << f.to_string();
}

inline fraction abs(const fraction &f) {
  return fraction(abs(f.nume), abs(f.deno));
}

typedef vector<fraction> vec;
typedef vector<vec> mat;

// Ax = bを解く Aは正方行列
vec gauss_jordan(const mat &A, const vec &b) {
  const int n = A.size();
  mat B(n, vec(n + 1));

  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      B[i][j] = A[i][j];
    }
  }

  for (int i = 0; i < n; ++i) {
    B[i][n] = b[i];
  }

  for (int i = 0; i < n; ++i) {
    dump(i);
    int pivot = i;
    for (int j = i; j < n; ++j) {
      if (abs(B[pivot][i]) < abs(B[j][i]))
        pivot = j;
    }
    B[i].swap(B[pivot]);

    if (B[i][i].nume == 0)
      break;

    // 使わないところは計算しない
    for (int j = i + 1; j <= n; ++j) {
      B[i][j] /= B[i][i];
    }

    for (int j = 0; j < n; ++j) {
      if (i != j) {
        for (int k = i + 1; k <= n; ++k) {
          B[j][k] -= B[j][i] * B[i][k];
        }
      }
    }
  }

  vec x(n);
  for (int i = 0; i < n; ++i) {
    x[i] = B[i][n];
  }
  return x;
}

inline long long lcm(long long a, long long b) { return a / __gcd(a, b) * b; }

int number(string::const_iterator &it);
unordered_map<int, int> unit(string::const_iterator &it);
unordered_map<int, int> molecule(string::const_iterator &it);

unordered_map<string, int> converter;

int number(string::const_iterator &it) {
  int res = 0;
  while (isdigit(*it)) {
    res = res * 10 + *it - '0';
    ++it;
  }
  return res;
}

unordered_map<int, int> unit(string::const_iterator &it) {
  unordered_map<int, int> res;

  if (*it == '(') {
    ++it;
    res = molecule(it);
    assert(*it == ')');
    ++it;
  } else {
    string name(1, *it);
    ++it;
    while (islower(*it)) {
      name += *it;
      ++it;
    }

    if (!converter.count(name))
      converter.insert({name, converter.size()});
    res[converter[name]] = 1;
  }

  if (isdigit(*it)) {
    const int num = number(it);
    for (auto &e : res)
      e.second *= num;
  }
  return res;
}

unordered_map<int, int> molecule(string::const_iterator &it) {
  unordered_map<int, int> res = unit(it);

  while (isupper(*it) || *it == '(') {
    for (const auto &e : unit(it)) {
      res[e.first] += e.second;
    }
  }
  return res;
}

vector<unordered_map<int, int>> parse(const string &s) {
  auto it = s.cbegin();
  vector<unordered_map<int, int>> res;
  res.emplace_back(molecule(it));

  while (*it == '+') {
    ++it;
    res.emplace_back(molecule(it));
  }
  return res;
}

int main() {
  cin.tie(nullptr);
  ios::sync_with_stdio(false);

  for (string equation; cin >> equation && equation[0] != '.';) {
    converter.clear();
    const int pos = equation.find('>');

    auto left = parse(equation.substr(0, pos));
    auto right = parse(equation.substr(pos + 1));

    const int n = converter.size();
    const int l = left.size();
    const int r = right.size();
    const int m = l + r;

    const int size = max(n + 1, m);

    mat A(size, vec(size, 0));
    for (int i = 0; i < n; ++i) {
      for (int j = 0; j < l; ++j) {
        A[i][j] = left[j][i];
      }

      for (int j = 0; j < r; ++j) {
        A[i][j + l] = -right[j][i];
      }
    }
    A[n][0] = 1;

    vec b(n + 1);
    b[n] = 1;

    dump(equation);
    dump(converter);
    dump(left);
    dump(right);
    dump(A);
    dump(b);

    auto x = gauss_jordan(A, b);
    long long c = 1;
    for (const auto &e : x) {
      c = lcm(c, e.deno);
    }

    for (int i = 0; i < m; ++i) {
      cout << abs(c / x[i].deno * x[i].nume) << (i + 1 == m ? '\\n' : ' ');
    }
  }

  return EXIT_SUCCESS;
}

Error: 0

Fixed submission:

#include <bits/stdc++.h>

#ifdef LOCAL
#include "dump.hpp"
#else
#define dump(...)
#endif

using namespace std;

struct fraction {
  typedef long long int_t;
  int_t nume, deno;

  static int_t gcd(int_t a, int_t b) { return __gcd(abs(a), abs(b)); }

  void reduce() {
    const int_t g = gcd(nume, deno);
    nume /= g;
    deno /= g;
  }

  fraction(int_t nume_ = 0, int_t deno_ = 1) : nume(nume_), deno(deno_) {
    reduce();
  }
  fraction(const fraction &f) : nume(f.nume), deno(f.deno) {}

  fraction &operator+=(const fraction &f) {
    const int_t r_deno = deno / __gcd(deno, f.deno) * f.deno;
    nume = r_deno / deno * nume + r_deno / f.deno * f.nume;
    deno = r_deno;
    reduce();
    return *this;
  }

  fraction &operator-=(const fraction &f) {
    return *this += fraction(-f.nume, f.deno);
  }

  fraction &operator*=(const fraction &f) {
    const int_t g1 = gcd(nume, f.deno);
    const int_t g2 = gcd(f.nume, deno);
    nume = (nume / g1) * (f.nume / g2);
    deno = (deno / g2) * (f.deno / g1);
    return *this;
  }

  fraction &operator/=(const fraction &f) {
    return *this *= fraction(f.deno, f.nume);
  }

  fraction operator+(const fraction &f) const { return fraction(*this) += f; }

  fraction operator-(const fraction &f) const { return fraction(*this) -= f; }

  fraction operator*(const fraction &f) const { return fraction(*this) *= f; }

  fraction operator/(const fraction &f) const { return fraction(*this) /= f; }

  bool operator==(const fraction &f) const {
    return nume == f.nume && deno == f.deno;
  }

  bool operator<(const fraction &f) const {
    const int_t lcm_deno = deno / gcd(deno, f.deno) * f.deno;
    return lcm_deno / deno * nume < lcm_deno / f.deno * f.nume;
  }

  string to_string() const {
    return std::to_string(nume) + "/" + std::to_string(deno);
  }

  double to_double() const { return (double)nume / deno; }

  long double to_long_double() const { return (long double)nume / deno; }
};

inline fraction abs(const fraction &f) {
  return fraction(abs(f.nume), abs(f.deno));
}

typedef vector<fraction> vec;
typedef vector<vec> mat;

// Ax = bを解く Aは正方行列
vec gauss_jordan(const mat &A, const vec &b) {
  const int n = A.size();
  mat B(n, vec(n + 1));

  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      B[i][j] = A[i][j];
    }
  }

  for (int i = 0; i < n; ++i) {
    B[i][n] = b[i];
  }

  for (int i = 0; i < n; ++i) {
    int pivot = i;
    for (int j = i; j < n; ++j) {
      if (abs(B[pivot][i]) < abs(B[j][i]))
        pivot = j;
    }
    B[i].swap(B[pivot]);

    if (B[i][i].nume == 0)
      break;

    // 使わないところは計算しない
    for (int j = i + 1; j <= n; ++j) {
      B[i][j] /= B[i][i];
    }

    for (int j = 0; j < n; ++j) {
      if (i != j) {
        for (int k = i + 1; k <= n; ++k) {
          B[j][k] -= B[j][i] * B[i][k];
        }
      }
    }
  }

  vec x(n);
  for (int i = 0; i < n; ++i) {
    x[i] = B[i][n];
  }
  return x;
}

inline long long lcm(long long a, long long b) { return a / __gcd(a, b) * b; }

int number(string::const_iterator &it);
unordered_map<int, int> unit(string::const_iterator &it);
unordered_map<int, int> molecule(string::const_iterator &it);

unordered_map<string, int> converter;

int number(string::const_iterator &it) {
  int res = 0;
  while (isdigit(*it)) {
    res = res * 10 + *it - '0';
    ++it;
  }
  return res;
}

unordered_map<int, int> unit(string::const_iterator &it) {
  unordered_map<int, int> res;

  if (*it == '(') {
    ++it;
    res = molecule(it);
    assert(*it == ')');
    ++it;
  } else {
    string name(1, *it);
    ++it;
    while (islower(*it)) {
      name += *it;
      ++it;
    }

    if (!converter.count(name))
      converter.insert({name, converter.size()});
    res[converter[name]] = 1;
  }

  if (isdigit(*it)) {
    const int num = number(it);
    for (auto &e : res)
      e.second *= num;
  }
  return res;
}

unordered_map<int, int> molecule(string::const_iterator &it) {
  unordered_map<int, int> res = unit(it);

  while (isupper(*it) || *it == '(') {
    for (const auto &e : unit(it)) {
      res[e.first] += e.second;
    }
  }
  return res;
}

vector<unordered_map<int, int>> parse(const string &s) {
  auto it = s.cbegin();
  vector<unordered_map<int, int>> res;
  res.emplace_back(molecule(it));

  while (*it == '+') {
    ++it;
    res.emplace_back(molecule(it));
  }
  return res;
}

int main() {
  cin.tie(nullptr);
  ios::sync_with_stdio(false);

  for (string equation; cin >> equation && equation[0] != '.';) {
    converter.clear();
    const int pos = equation.find('>');

    auto left = parse(equation.substr(0, pos));
    auto right = parse(equation.substr(pos + 1));

    const int n = converter.size();
    const int l = left.size();
    const int r = right.size();
    const int m = l + r;

    mat A(n + 1, vec(m, 0));
    for (int i = 0; i < n; ++i) {
      for (int j = 0; j < l; ++j) {
        A[i][j] = left[j][i];
      }

      for (int j = 0; j < r; ++j) {
        A[i][j + l] = -right[j][i];
      }
    }
    A[n][0] = 1;

    vec b(n + 1);
    b[n] = 1;

    auto x = gauss_jordan(A, b);
    long long c = 1;
    for (const auto &e : x) {
      c = lcm(c, e.deno);
    }

    for (int i = 0; i < m; ++i) {
      cout << c / x[i].deno * x[i].nume << (i + 1 == m ? '\\n' : ' ');
    }
  }

  return EXIT_SUCCESS;
}