Problem p01555 (C++) — buggy submission, verdict: Memory Limit Exceeded

#include <iostream>
#include <stdio.h>
#include <string>
#define llint long long int

using namespace std;

llint s;

int getKeta(llint n) {
  int ret = 0;
  for (; n > 0; n /= 10)
    ret++;
  return ret;
}

llint intpow(int a, int b) {
  llint seki = 1;
  for (; b > 0; b--)
    seki *= a;
  return seki;
}

llint count(llint n) {
  int keta = getKeta(n);
  llint ret = keta * n;

  llint sub = 0;
  for (int i = 1; i < keta; i++) {
    sub = sub * 10 + 9;
    ret -= sub;
  }

  for (int i = 1; i <= keta - 1; i++) {
    ret -= (intpow(10, i) - 1) / 3 * i;
    ret -= (intpow(10, i) - 1) / 5 * i;
    ret += (intpow(10, i) - 1) / 15 * i;
    ret += (intpow(10, i - 1) - 1) / 3 * i;
    ret += (intpow(10, i - 1) - 1) / 5 * i;
    ret -= (intpow(10, i - 1) - 1) / 15 * i;
  }

  ret -= n / 3 * keta;
  ret -= n / 5 * keta;
  ret += n / 15 * keta;
  ret += (intpow(10, keta - 1) - 1) / 3 * keta;
  ret += (intpow(10, keta - 1) - 1) / 5 * keta;
  ret -= (intpow(10, keta - 1) - 1) / 15 * keta;

  ret += n / 3 * 4;
  ret += n / 5 * 4;

  return ret;
}

string makestr(llint n) {
  string ret;
  char buf[256];

  for (llint i = n; i < n + 40; i++) {
    if (i % 3 == 0)
      ret += "Fizz";
    if (i % 5 == 0)
      ret += "Buzz";
    if (i % 3 && i % 5) {
      sprintf(buf, "%lld", i);
      ret += buf;
    }
  }
  return ret;
}

int main(void) {
  cin >> s;

  llint left = 0, right = 90000000000000000, mid;
  while (right > left + 1) {
    mid = (left + right) / 2;
    if (count(mid) < s) {
      if (count(mid + 1) >= s) {
        left = mid;
        break;
      } else {
        left = mid + 1;
      }
    } else {
      right = mid;
    }

    // cout << left << ", " << right << endl;
  }

  cout << makestr(left + 1).substr(s - count(left) - 1, 20) << endl;
  return 0;
}

Error: MLE

Fixed submission:

#include <iostream>
#include <stdio.h>
#include <string>
#define llint long long int

using namespace std;

llint s;

int getKeta(llint n) {
  int ret = 0;
  for (; n > 0; n /= 10)
    ret++;
  return ret;
}

llint intpow(int a, int b) {
  llint seki = 1;
  for (; b > 0; b--)
    seki *= a;
  return seki;
}

llint count(llint n) {
  int keta = getKeta(n);
  llint ret = keta * n;

  for (int i = 1, sub = 0; i < keta; i++) {
    sub = sub * 10 + 9;
    ret -= sub;
  }

  for (int i = 1; i <= keta - 1; i++) {
    ret -= (intpow(10, i) - 1) / 3 * i;
    ret -= (intpow(10, i) - 1) / 5 * i;
    ret += (intpow(10, i) - 1) / 15 * i;
    ret += (intpow(10, i - 1) - 1) / 3 * i;
    ret += (intpow(10, i - 1) - 1) / 5 * i;
    ret -= (intpow(10, i - 1) - 1) / 15 * i;
  }

  ret -= n / 3 * keta;
  ret -= n / 5 * keta;
  ret += n / 15 * keta;
  ret += (intpow(10, keta - 1) - 1) / 3 * keta;
  ret += (intpow(10, keta - 1) - 1) / 5 * keta;
  ret -= (intpow(10, keta - 1) - 1) / 15 * keta;

  ret += n / 3 * 4;
  ret += n / 5 * 4;

  return ret;
}

string makestr(llint n) {
  string ret;
  for (int i = n; i < n + 40; i++) {
    if (i % 3 == 0)
      ret += "Fizz";
    if (i % 5 == 0)
      ret += "Buzz";
    if (i % 3 && i % 5) {
      char buf[256];
      sprintf(buf, "%d", i);
      ret += buf;
    }
  }
  return ret;
}

int main(void) {
  cin >> s;

  llint left = 0, right = 100000000000000, mid;
  while (right > left + 1) {
    mid = (left + right) / 2;
    if (count(mid) < s) {
      if (count(mid + 1) >= s) {
        left = mid;
        break;
      } else {
        left = mid + 1;
      }
    } else {
      right = mid;
    }

    cout << left << ", " << right << endl;
  }

  cout << makestr(left + 1).substr(s - count(left) - 1, 20) << endl;
  return 0;
}