Problem p00208 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <algorithm>
#include <assert.h>
#include <iostream>
#include <map>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <vector>

using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
static const double EPS = 1e-9;
static const double PI = acos(-1.0);

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOREQ(i, s, n) for (int i = (s); i <= (int)(n); i++)
#define FORIT(it, c)                                                           \\
  for (__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++)
#define MEMSET(v, h) memset((v), h, sizeof(v))

map<ll, ll> memo;
ll calc(ll n, ll digit) {
  if (n == digit * 10 - 1 && memo.count(n)) {
    return memo[n];
  }
  ll ret = 0;
  int d = n / digit;
  if (digit == 1) {
    if (d >= 6) {
      ret--;
    }
    if (d >= 4) {
      ret--;
    }
    ret += d + 1;
  } else {
    if (n / digit == 0) {
      return calc(n, digit / 10);
    }
    if (d == 4) {
      ret = 4 * calc(digit - 1, digit / 10);
    } else if (d == 6) {
      ret = 5 * calc(digit - 1, digit / 10);
    } else {
      if (d >= 6) {
        d -= 2;
      } else if (d >= 4) {
        d -= 1;
      }
      ret = d * calc(digit - 1, digit / 10);
      ret += calc(n % digit, digit / 10);
    }
  }
  if (n == digit * 10 - 1) {
    memo[n] = ret;
  }
  return ret;
}

int main() {
  ll n;
  while (scanf("%lld", &n), n) {
    ll left = n;
    ll right = 10000000000LL;
    while (left != right) {
      ll mid = (left + right) / 2;
      if (calc(mid, 1000000000) - 1 < n) {
        left = mid + 1;
      } else {
        right = mid;
      }
    }
    printf("%lld\\n", left);
  }
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <assert.h>
#include <iostream>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <vector>

using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
static const double EPS = 1e-9;
static const double PI = acos(-1.0);

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOREQ(i, s, n) for (int i = (s); i <= (int)(n); i++)
#define FORIT(it, c)                                                           \\
  for (__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++)
#define MEMSET(v, h) memset((v), h, sizeof(v))

ll calc(ll n, int digit) {
  assert(digit != 0);
  ll ret = 0;
  int d = n / digit;
  if (digit == 1) {
    if (d >= 6) {
      ret--;
    }
    if (d >= 4) {
      ret--;
    }
    ret += d + 1;
  } else {
    if (n / digit == 0) {
      return calc(n, digit / 10);
    }
    if (d == 4) {
      ret = 4 * calc(digit - 1, digit / 10);
    } else if (d == 6) {
      ret = 5 * calc(digit - 1, digit / 10);
    } else {
      if (d >= 6) {
        d -= 2;
      } else if (d >= 4) {
        d -= 1;
      }
      ret = d * calc(digit - 1, digit / 10);
      ret += calc(n % digit, digit / 10);
    }
  }
  return ret;
}

int main() {
  ll n;
  while (scanf("%lld", &n), n) {
    ll left = n;
    ll right = 10000000000LL;
    while (left != right) {
      ll mid = (left + right) / 2;
      if (calc(mid, 1000000000) - 1 < n) {
        left = mid + 1;
      } else {
        right = mid;
      }
    }
    printf("%lld\\n", left);
  }
}