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

#include <algorithm>
#include <cassert>
#include <cctype>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>
using namespace std;
inline int toInt(string s) {
  int v;
  istringstream sin(s);
  sin >> v;
  return v;
}
template <class T> inline string toString(T x) {
  ostringstream sout;
  sout << x;
  return sout.str();
}
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<string> vs;
typedef pair<int, int> pii;
typedef long long ll;
#define ALL(a) (a).begin(), (a).end()
#define RALL(a) (a).rbegin(), (a).rend()
#define EXIST(s, e) ((s).find(e) != (s).end())
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define REP(i, n) FOR(i, 0, n)
#define EACH(t, i, c) for (t::iterator i = (c).begin(); i != (c).end(); ++i)
const double EPS = 1e-10;
const double PI = acos(-1.0);

ll mypow10(ll n) {
  ll ret = 1;
  for (ll i = 0; i < n; i++) {
    ret *= 10;
  }
  return ret;
}

ll get_chs(ll n) {
  ll digit = toString(n).size();
  ll chs = 0;
  for (ll i = 1; i < digit; i++) {
    chs += i * (mypow10(i) - mypow10(i - 1));
  }
  assert(chs >= 0);
  for (ll i = 1; i < digit; i++) {
    ll a = mypow10(i) - 1;
    ll b = mypow10(i - 1) - 1;
    chs += (a / 3 - b / 3) * 4 + (a / 5 - b / 5) * 4;
    chs -= (a / 3 - b / 3) * i + (a / 5 - b / 5) * i - (a / 15 - b / 15) * i;
  }
  assert(chs >= 0);
  ll remain = n - (mypow10(digit - 1) - 1);
  ll n2 = mypow10(digit - 1) - 1;
  assert(n2 >= 0);
  chs += remain * digit;
  assert(chs >= 0);
  chs += (n / 3 - n2 / 3) * 4 + (n / 5 - n2 / 5) * 4;
  assert(chs >= 0);
  chs -= (n / 3 - n2 / 3) * (digit) + (n / 5 - n2 / 5) * (digit) -
         (n / 15 - n2 / 15) * digit;
  assert(chs >= 0);
  return chs;
}

int main() {
  ll n;
  cin >> n;
  ll lb = 0, ub = mypow10(17);
  while (ub - lb > 1) {
    ll mid = (lb + ub) / 2;
    ll chs = get_chs(mid);
    if (chs >= n) {
      ub = mid;
    } else {
      lb = mid;
    }
  }

  ll prev_chs = (ub == 1 ? 0 : get_chs(ub - 1));
  ll cur_chs = get_chs(ub);
  string s;
  ll cur = ub;
  while (s.size() < 20 + n - (prev_chs + 1)) {
    if (cur % 3 == 0) {
      if (cur % 5 == 0) {
        s += "FizzBuzz";
      } else {
        s += "Fizz";
      }
    } else {
      if (cur % 5 == 0) {
        s += "Buzz";
      } else {
        s += toString(cur);
      }
    }
    cur++;
  }

  cout << s.substr(n - (prev_chs + 1), 20) << endl;
}

Error: 0

Fixed submission:

#include <algorithm>
#include <cassert>
#include <cctype>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>
using namespace std;
inline int toInt(string s) {
  int v;
  istringstream sin(s);
  sin >> v;
  return v;
}
template <class T> inline string toString(T x) {
  ostringstream sout;
  sout << x;
  return sout.str();
}
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<string> vs;
typedef pair<int, int> pii;
typedef long long ll;
#define ALL(a) (a).begin(), (a).end()
#define RALL(a) (a).rbegin(), (a).rend()
#define EXIST(s, e) ((s).find(e) != (s).end())
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define REP(i, n) FOR(i, 0, n)
#define EACH(t, i, c) for (t::iterator i = (c).begin(); i != (c).end(); ++i)
const double EPS = 1e-10;
const double PI = acos(-1.0);

ll pow10(ll n) {
  ll ret = 1;
  for (ll i = 0; i < n; i++) {
    ret *= 10;
  }
  return ret;
}

ll get_chs(ll n) {
  ll digit = toString(n).size();
  ll chs = 0;
  for (ll i = 1; i < digit; i++) {
    chs += i * pow10(i);
  }
  assert(chs >= 0);
  for (ll i = 1; i < digit; i++) {
    ll a = pow10(i) - 1;
    ll b = pow10(i - 1) - 1;
    chs += (a / 3 - b / 3) * 4 + (a / 5 - b / 5) * 4;
    chs -= (a / 3 - b / 3) * i + (a / 5 - b / 5) * i;
  }
  assert(chs >= 0);
  ll remain = n - pow10(digit - 1);
  ll n2 = pow10(digit - 1) - 1;
  assert(n2 >= 0);
  chs += remain * digit;
  assert(chs >= 0);
  if (remain != 0 && (remain * digit) / remain != digit) {
    assert(0); // overflow handling
  }
  assert(n / 5 - n2 / 5 >= 0);
  chs += (n / 3 - n2 / 3) * 4 + (n / 5 - n2 / 5) * 4;
  assert(chs >= 0);
  chs -= (n / 3 - n2 / 3) * (digit) + (n / 5 - n2 / 5) * (digit);
  assert(chs >= 0);
  return chs + 1;
}

int main() {
  ll n;
  cin >> n;

  ll lb = 1, ub = n;
  while (ub - lb > 1) {
    ll mid = (lb + ub) / 2;
    ll chs = get_chs(mid);
    if (chs >= n) {
      ub = mid;
    } else {
      lb = mid;
    }
  }

  ll prev_chs = (ub == 1 ? 0 : get_chs(ub - 1));
  ll cur_chs = get_chs(ub);
  string s;
  ll cur = ub;
  while (s.size() < 20 + n - (prev_chs + 1)) {
    if (cur % 3 == 0) {
      if (cur % 5 == 0) {
        s += "FizzBuzz";
      } else {
        s += "Fizz";
      }
    } else {
      if (cur % 5 == 0) {
        s += "Buzz";
      } else {
        s += toString(cur);
      }
    }
    cur++;
  }

  cout << s.substr(n - (prev_chs + 1), 20) << endl;
}