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

#include <functional>
#include <iostream>
#include <map>
#include <string>
#include <tuple>
#include <unordered_map>
#include <utility>
#include <vector>
using namespace std;
int main(int argc, char *argv[]) {
  string s;
  cin >> s;
  const int n = s.size();
  vector<int> ds;
  int sum = 0;
  long long prod = 1;
  for (int i = 0; i < n; i++) {
    ds.push_back(s[i] - '0');
    sum += ds.back();
    prod *= (ds.back() + 1);
  }
  // struct myhash : public std::unary_function<pair<long long,int>,
  // std::size_t> {
  //   std::size_t operator()(const pair<long long,int>& k) const {
  //     return ((std::get<0>(k) & 0xffffffff) + ((std::get<0>(k) >> 32) &
  //     0xffffffff))  + std::get<1>(k);
  //   }
  // };
  // vector<vector<unordered_map<pair<long long,int>,long long,myhash>>>
  // mem(n+1, vector<unordered_map<pair<long long,int>,long
  // long,myhash>>(10*n));
  vector<vector<map<pair<long long, int>, long long>>> mem(
      n + 1, vector<map<pair<long long, int>, long long>>(10 * n));

  function<long long(int, int, long long, int)> rec =
      [n, sum, prod, &ds, &rec, &mem](int k, int s, long long p, int cmp) {
        auto pcmp = make_pair(p, cmp);
        auto it = mem[k][s].find(pcmp);
        if (it != mem[k][s].end())
          return it->second;
        long long cnt = 0;
        if (k == n) {
          if (s < sum || ((s == sum) && (p < prod)) ||
              ((s == sum) && (p == prod) && (cmp < 0)))
            cnt = 1;
          else
            cnt = 0;
        } else {
          // k-th digit
          for (int d = 0; d < 10; d++) {
            if (s + d > sum)
              break; // no more
            int dd = d - ds[k];
            if (dd < 0)
              dd = -1;
            if (dd > 0)
              dd = 1;
            cnt += rec(k + 1, s + d, p * (d + 1), cmp == 0 ? dd : cmp);
          }
        }
        mem[k][s][pcmp] = cnt;
        return cnt;
      };
  cout << rec(0, 0, 1, 0) << endl;

  return 0;
}


Error: TLE

Fixed submission:

#include <functional>
#include <iostream>
#include <map>
#include <string>
#include <tuple>
#include <unordered_map>
#include <utility>
#include <vector>
using namespace std;
int main(int argc, char *argv[]) {
  string s;
  cin >> s;
  const int n = s.size();
  vector<int> ds;
  int sum = 0, prod = 1;
  for (int i = 0; i < n; i++) {
    ds.push_back(s[i] - '0');
    sum += ds.back();
    prod *= (ds.back() + 1);
  }
  // struct myhash : public std::unary_function<tuple<int,int,long long,int>,
  // std::size_t> {
  //   std::size_t operator()(const tuple<int,int,long long,int>& k) const {
  //     return (std::get<0>(k) * 1021) ^ (std::get<1>(k)*37) ^ ((std::get<2>(k)
  //     & 0xffffffff) + ((std::get<2>(k) >> 32) & 0xffffffff))  +
  //     std::get<3>(k);
  //   }
  // };
  // unordered_map<tuple<int,int,long long,int>,long long, myhash> mem;
  // map<tuple<int,int,long long,int>,long long> mem;

  struct myhash
      : public std::unary_function<pair<long long, int>, std::size_t> {
    std::size_t operator()(const pair<long long, int> &k) const {
      return ((std::get<0>(k) & 0xffffffff) +
              ((std::get<0>(k) >> 32) & 0xffffffff)) +
             std::get<1>(k);
    }
  };
  // vector<vector<map<pair<long long,int>,long long>>> mem(n+1,
  // vector<map<pair<long long,int>,long long>>(10*n));
  vector<vector<unordered_map<pair<long long, int>, long long, myhash>>> mem(
      n + 1,
      vector<unordered_map<pair<long long, int>, long long, myhash>>(10 * n));

  function<long long(int, int, long long, int)> rec =
      [n, sum, prod, &ds, &rec, &mem](int k, int s, long long p, int cmp) {
        // auto kspcmp = make_tuple(k,s,p,cmp);
        // auto it = mem.find(kspcmp);
        // if(it != mem.end()) return it->second;
        auto pcmp = make_pair(p, cmp);
        auto it = mem[k][s].find(pcmp);
        if (it != mem[k][s].end())
          return it->second;
        long long cnt = 0;
        if (k == n) {
          if (s < sum || ((s == sum) && (p < prod)) ||
              ((s == sum) && (p == prod) && (cmp < 0)))
            cnt = 1;
          else
            cnt = 0;
        } else {
          // k-th digit
          for (int d = 0; d < 10; d++) {
            if (s + d > sum)
              break; // no more
            cnt += rec(k + 1, s + d, p * (d + 1), cmp == 0 ? (d - ds[k]) : cmp);
          }
        }
        // mem[kspcmp] = cnt;
        mem[k][s][pcmp] = cnt;
        return cnt;
      };
  cout << rec(0, 0, 1, 0) << endl;

  return 0;
}