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

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
/*
全探索か
途中のD調整が分からない･･･。
逆算方式か。
これかも
3^60通りとかになっちゃう
むず、だめだ
逆算、あまりを+-して、2,3,5のどれかで割るの繰り返ししかありえない
%=0ならそのまま割るしかない
サンプル5行目がTLEだな

これ以上どこを効率化するんだ
bfsじゃなくてdfsで実装すればいい？
直感的にはそのほうがケースへりそうだけど、それだけかな・・・

やりたいことあってた、けど実装力全然足らない･･･。
*/

ll N, A, B, C, D, high = 4e18;
map<ll, ll> M;
ll dfs(ll n) {
  if (n == 0)
    return 0;
  if (n == 1)
    return D;
  if (M.count(n))
    return M[n];
  M[n] = 4e18;
  if (log10(n * D) < 18)
    M[n] = min(M[n], n * D);
  M[n] = min(M[n], dfs(n / 2) + A + n % 2 * D);
  M[n] = min(M[n], dfs(n / 2 + 1) + A + (2 - n % 2) * D);
  M[n] = min(M[n], dfs(n / 3) + B + n % 3 * D);
  M[n] = min(M[n], dfs(n / 3 + 1) + B + (3 - n % 3) * D);
  M[n] = min(M[n], dfs(n / 5) + C + n % 5 * D);
  M[n] = min(M[n], dfs(n / 5 + 1) + C + (5 - n % 5) * D);
  return M[n];
}

int main() {
  ll T;
  cin >> T;
  for (ll i = 0; i < T; i++) {
    M.clear();
    cin >> N >> A >> B >> C >> D;
    cout << dfs(N) << endl;
  }
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
ll high = 1000000000000000001;
/*
全探索か
途中のD調整が分からない･･･。
逆算方式か。
これかも
3^60通りとかになっちゃう
むず、だめだ
逆算、あまりを+-して、2,3,5のどれかで割るの繰り返ししかありえない
%=0ならそのまま割るしかない
サンプル5行目がTLEだな

これ以上どこを効率化するんだ
*/

queue<pair<ll, ll>> Q;
ll N, A, B, C, D;
ll bfs() {
  map<ll, ll> M;

  M[0] = high;
  while (!Q.empty()) {
    auto n = Q.front();
    Q.pop();
    ll n1 = n.first;
    ll n2 = n.second;
    if (M[n1] != 0 && M[n1] < n2)
      continue;
    if (n1 == 1) {
      M[0] = min(M[0], n2 + D);
      continue;
    }
    if (n1 == 0) {
      M[0] = min(M[0], n2);
      continue;
    }
    if (log10(A) > log10(((2 + n1) / 2) * D))
      M[0] = min(M[0], n2 + n1 * D);
    else if (n1 % 2 == 0) {
      Q.emplace(make_pair(n1 / 2, n2 + A));
      M[n1 / 2] = n2 + A;
    } else {
      Q.emplace(make_pair((n1 + 1) / 2, n2 + A + D));
      if (M[(n1 + 1) / 2] == 0)
        M[(n1 + 1) / 2] = n2 + A + D;
      else
        M[(n1 + 1) / 2] = min(M[(n1 + 1) / 2], n2 + A + D);
      Q.emplace(make_pair((n1 - 1) / 2, n2 + A + D));
      if (M[(n1 - 1) / 2])
        M[(n1 - 1) / 2] = n2 + A + D;
      else
        M[(n1 - 1) / 2] = min(M[(n1 - 1) / 2], n2 + A + D);
    }
    if (log10(B) > log10(((3 + n1) / 3) * D))
      M[0] = min(M[0], n2 + n1 * D);
    else if (n1 % 3 == 0) {
      Q.emplace(make_pair(n1 / 3, n2 + B));
      M[n1 / 3] = n2 + B;
    } else {
      ll a = 3 - n1 % 3, b = n1 % 3;
      Q.emplace(make_pair((n1 + (3 - n1 % 3)) / 3, n2 + B + D * a));
      if (M[(n1 + a) / 3] == 0)
        M[(n1 + a) / 3] = n2 + B + D * a;
      else
        M[(n1 + a) / 3] = min(M[(n1 + a) / 3], n2 + B + D * a);
      Q.emplace(make_pair((n1 - b) / 3, n2 + B + b * D));
      if (M[(n1 - b) / 3] == 0)
        M[(n1 - b) / 3] = n2 + B + b * D;
      else
        M[(n1 - b) / 3] = min(M[(n1 - b) / 3], n2 + B + b * D);
    }
    if (log10(C) > log10(((5 + n1) / 5) * D))
      M[0] = min(M[0], n2 + n1 * D);
    else if (n1 % 5 == 0) {
      Q.emplace(make_pair(n1 / 5, n2 + C));
      if (M[n1 / 5] == 0)
        M[n1 / 5] = n2 + C;
      else
        M[n1 / 5] = min(M[n1 / 5], n2 + C);
    } else {
      ll a = 5 - n1 % 5, b = n1 % 5;
      Q.emplace(make_pair((n1 + a) / 5, n2 + C + D * a));
      if (M[(n1 + a) / 5] == 0)
        M[(n1 + a) / 5] = n2 + C + D * a;
      else
        M[(n1 + a) / 5] = min(M[(n1 + a) / 5], n2 + C + D * a);
      Q.emplace(make_pair((n1 - b) / 5, n2 + C + b * D));
      if (M[(n1 - b) / 5] == 0)
        M[(n1 - b) / 5] = n2 + C + b * D;
      else
        M[(n1 - b) / 5] = min(M[(n1 - b) / 5], n2 + C + b * D);
    }
  }
  return M[0];
}

int main() {
  ll T;
  cin >> T;
  for (ll n = 0; n < T; n++) {
    cin >> N >> A >> B >> C >> D;
    ll ans = high;
    Q.emplace(make_pair(N, 0));
    cout << bfs() << endl;
  }
}