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

#include <algorithm>
#include <iostream>
namespace boost {
template <class T> struct integer_iterator {
  T a;
  bool operator!=(integer_iterator const &it) const { return a != it.a; }
  T operator*() const { return a; }
  integer_iterator &operator++() {
    ++a;
    return *this;
  }
  integer_iterator operator++(int) { return {a++}; }
};
template <class T> struct integer_range {
  T l, r;
  typedef integer_iterator<T> iterator;
  iterator begin() const { return {l}; }
  iterator end() const { return {r}; }
};
template <class T> integer_range<T> irange(T l, T r) { return {l, r}; }
template <class T> struct integer_iterator_with_step {
  T a, d, i;
  bool operator!=(integer_iterator_with_step const &it) const {
    return a != it.a or d != it.d or i != it.i;
  }
  T operator*() const { return a + d * i; }
  integer_iterator_with_step &operator++() {
    ++i;
    return *this;
  }
  integer_iterator_with_step operator++(int) { return {a, d, i++}; }
};
template <class T> struct strided_integer_range {
  T l, r, s;
  typedef integer_iterator_with_step<T> iterator;
  iterator begin() const { return {l, s, 0}; }
  iterator end() const { return {l, s, (r - l) / s}; }
};
template <class T> strided_integer_range<T> irange(T l, T r, T s) {
  return {l, r, s};
}
} // namespace boost
#include <cassert>
#include <cmath>
#include <complex>
#include <sstream>
#include <vector>
// O (n log n)
template <typename T>
void fft_inplace(std::vector<std::complex<T>> &f, int dir) {
  using namespace std;
  using namespace boost;
  int n = f.size();
  assert(n == pow(2, log2(n)));
  if (n == 1)
    return;
  vector<complex<T>> a(n / 2), b(n / 2);
  for (int i : irange(0, n / 2)) {
    a[i] = f[2 * i];
    b[i] = f[2 * i + 1];
  }
  fft_inplace(a, dir);
  fft_inplace(b, dir);
  const complex<T> zeta = polar<T>(1, dir * 2 * M_PI / n);
  complex<T> pow_zeta = 1;
  for (int i : irange(0, n)) {
    f[i] = a[i % (n / 2)] + pow_zeta * b[i % (n / 2)];
    pow_zeta *= zeta;
  }
}
template <typename T>
std::vector<std::complex<T>> fft(std::vector<std::complex<T>> f) {
  using namespace std;
  f.resize(pow(2, ceil(log2(f.size()))));
  fft_inplace(f, +1);
  return f;
}
template <typename T>
std::vector<std::complex<T>> ifft(std::vector<std::complex<T>> f) {
  using namespace std;
  f.resize(pow(2, ceil(log2(f.size()))));
  fft_inplace(f, -1);
  return f;
}
template <typename T, typename R = double>
std::vector<T> convolution(std::vector<T> const &a, std::vector<T> const &b) {
  using namespace std;
  using namespace boost;
  int m = a.size() + b.size() - 1;
  int n = pow(2, ceil(log2(m)));
  vector<complex<R>> x(n), y(n);
  copy(a.begin(), a.end(), x.begin());
  copy(b.begin(), b.end(), y.begin());
  x = fft(x);
  y = fft(y);
  vector<complex<R>> z(n);
  for (int i : irange(0, n))
    z[i] = x[i] * y[i];
  z = ifft(z);
  vector<T> c(m);
  for (int i : irange(0, m))
    c[i] = round(z[i].real() / n);
  return c;
}
namespace boost {
namespace multiprecision {
struct cpp_int {
  typedef long long ll;
  bool sign;
  std::vector<ll> ds;
  static constexpr int p = 10;
  void normalize() {
    for (int i = 0; i < ds.size() /* may be changed in loop */; ++i) {
      if (not(0 <= ds[i] and ds[i] < p)) {
        if (not(i + 1 < ds.size()))
          ds.push_back(0);
        ds[i + 1] += ds[i] / p;
        ds[i] %= p;
        if (ds[i] < 0) {
          ds[i] += p;
          ds[i + 1] -= 1;
        }
      }
    }
    while (not ds.empty() and ds.back() == 0)
      ds.pop_back();
    if (ds.empty())
      sign = false;
  }
  cpp_int() : sign(false), ds(0) {}
  cpp_int(std::vector<ll> ds_) : sign(false), ds(ds_) { normalize(); }
  cpp_int(std::string const &s) {
    sign = (s.front() == '-');
    int t = sign ? 1 : 0;
    for (int i : boost::irange<int>(t, s.size()))
      assert('0' <= s[i] and s[i] <= '9');
    ds.resize(s.size() - t);
    for (int i : boost::irange<int>(t, s.size()))
      ds[ds.size() - (i - t) - 1] = s[i] - '0';
    normalize();
  }
  std::string str() const {
    std::stringstream s;
    if (sign)
      s << '-';
    for (int i : boost::irange<int>(ds.size() - 1, -1, -1))
      s << (char)(ds[i] + '0');
    if (ds.empty())
      s << '0';
    return s.str();
  }
};
inline bool operator==(cpp_int const &a, cpp_int const &b) {
  return a.sign == b.sign and a.ds == b.ds;
}
inline bool operator!=(cpp_int const &a, cpp_int const &b) {
  return not(a == b);
}
inline bool operator<(cpp_int const &a, cpp_int const &b) {
  if (a.sign and not b.sign) {
    return true;
  } else if (not a.sign and b.sign) {
    return false;
  } else if (a.sign and b.sign) {
    if (a.ds.size() != b.ds.size()) {
      return a.ds.size() > b.ds.size();
    } else {
      return a.ds > b.ds;
    }
  } else {
    if (a.ds.size() != b.ds.size()) {
      return a.ds.size() < b.ds.size();
    } else {
      return a.ds < b.ds;
    }
  }
}
inline bool operator>=(cpp_int const &a, cpp_int const &b) {
  return not(a < b);
}
inline bool operator>(cpp_int const &a, cpp_int const &b) {
  return a >= b and a != b;
}
inline bool operator<=(cpp_int const &a, cpp_int const &b) {
  return a < b or a == b;
}
inline cpp_int &operator++(cpp_int &a) {
  a.ds.front() += 1;
  a.normalize();
  return a;
}
inline cpp_int &operator--(cpp_int &a) {
  a.ds.front() -= 1;
  a.normalize();
  return a;
}
inline cpp_int operator-(cpp_int a) {
  a.sign = not a.sign;
  return a;
}
inline cpp_int operator-(cpp_int const &a, cpp_int const &b);
inline cpp_int operator+(cpp_int const &a, cpp_int const &b) {
  if (a.sign and not b.sign) {
    return b - (-a);
  } else if (not a.sign and b.sign) {
    return a - (-b);
  } else if (a.sign and b.sign) {
    return -((-a) + (-b));
  } else {
    assert(not a.sign and not b.sign);
    int an = a.ds.size();
    int bn = b.ds.size();
    cpp_int c;
    c.ds.resize(std::max(an, bn));
    for (int i : boost::irange(0, an))
      c.ds[i] += a.ds[i];
    for (int i : boost::irange(0, bn))
      c.ds[i] += b.ds[i];
    c.normalize();
    return c;
  }
}
inline cpp_int operator-(cpp_int const &a, cpp_int const &b) {
  if (a.sign and not b.sign) {
    return -((-a) + b);
  } else if (not a.sign and b.sign) {
    return a + (-b);
  } else if (a.sign and b.sign) {
    return -((-a) - (-b));
  } else if (b > a) {
    return -(b - a);
  } else {
    assert(not a.sign and not b.sign and a >= b);
    int an = a.ds.size();
    int bn = b.ds.size();
    cpp_int c;
    c.ds.resize(std::max(an, bn));
    for (int i : boost::irange(0, an))
      c.ds[i] += a.ds[i];
    for (int i : boost::irange(0, bn))
      c.ds[i] -= b.ds[i];
    c.normalize();
    return c;
  }
}
inline cpp_int &operator+=(cpp_int &a, cpp_int const &b) {
  return a = a + b;
  return a;
}
inline cpp_int &operator-=(cpp_int &a, cpp_int const &b) {
  return a = a - b;
  return a;
}
inline cpp_int &operator*=(cpp_int &a, cpp_int const &b) {
  a.ds = convolution(a.ds, b.ds);
  a.normalize();
  a.sign = a.sign != b.sign;
  return a;
}
inline cpp_int operator*(cpp_int a, cpp_int const &b) { return a *= b; }
inline std::istream &operator>>(std::istream &input, cpp_int &a) {
  std::string s;
  input >> s;
  a = cpp_int(s);
  return input;
}
inline std::ostream &operator<<(std::ostream &output, cpp_int const &a) {
  return output << a.str();
}
} // namespace multiprecision
} // namespace boost
using namespace std;
using namespace boost;
using namespace boost::multiprecision;
#define MAX_DIGIT 80
int main() {
  int n;
  cin >> n;
  for (int testcase : irange(0, n)) {
    string a, b;
    cin >> a >> b;
    if (a.size() > MAX_DIGIT or b.size() > MAX_DIGIT) {
      cout << "overflow" << endl;
      continue;
    }
    string c = cpp_int(cpp_int(a) + cpp_int(b)).str();
    if (c.size() > MAX_DIGIT) {
      cout << "overflow" << endl;
      continue;
    }
    cout << c << endl;
  }
  return 0;
}

Error: WA

Fixed submission:

#include <algorithm>
#include <iostream>
using namespace std;
#define repeat(i, n) for (int i = 0; i < (n); ++i)
#define MAX_INPUT_DIGIT (80)
#define MAX_DIGIT (MAX_INPUT_DIGIT + 1)
int main() {
  int N;
  cin >> N;
  static int d[MAX_DIGIT];
  repeat(n, N) {
    fill(d, d + MAX_DIGIT, 0);
    repeat(i, 2) {
      string s;
      cin >> s;
      repeat(j, (int)s.length()) { d[j] += s[s.length() - 1 - j] - '0'; }
    }
    repeat(i, MAX_DIGIT - 1) {
      d[i + 1] += d[i] / 10;
      d[i] %= 10;
    }
    {
      int i = MAX_DIGIT - 1;
      while (d[i] == 0)
        --i;
      for (; 0 <= i; --i)
        cout << d[i];
      cout << endl;
    }
  }
  return 0;
}