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

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
ll f[2][10 * 14 + 2][20000][3];
ll n;
vector<ll> Hash;
int go[20010][10];
int number[15];
void init() {
  set<ll> s;
  s.insert(1);
  for (int i = 1; i <= 14; ++i) {
    set<ll> st;

    for (ll x : s) {
      for (int j = 1; j <= 10; ++j) {
        st.insert(x * j);
      }
    }
    for (ll x : st) {
      s.insert(x);
    }
  }

  for (ll x : s) {
    Hash.push_back(x);
  }
}
int getID(ll x) {
  int pos = lower_bound(Hash.begin(), Hash.end(), x) - Hash.begin();
  return pos;
}
char ch[20];
int main() {
  init();
  scanf("%s", ch);
  int len = strlen(ch);

  int ySum = 0;

  for (int i = len - 1; i >= 0; --i) {
    number[len - i] = ch[i] - '0';
    ySum += ch[i] - '0';
  }
  n = 1;
  for (int i = 0; i < len; ++i) {
    n = n * (ch[i] - '0' + 1);
  }

  int num = Hash.size();
  int yID = getID(n);

  for (int i = 0; i < num; ++i) {
    for (int j = 1; j <= 10; ++j) {
      int id = getID(Hash[i] * j);
      go[i][j - 1] = id;
    }
  }
  // printf("%d %lld\\n", ySum, n);
  for (int j = 0; j <= 9 * 14; ++j) {
    for (int k = 0; k < num; ++k) {
      for (int l = 0; l <= 2; ++l) {
        if (j < ySum) {
          f[0][j][k][l] = 1;
        }
        if (j == ySum && k < yID) {
          f[0][j][k][l] = 1;
        }
        if (j == ySum && k == yID && l == 0) {
          f[0][j][k][l] = 1;
        }
      }
    }
  }
  // for (int i = 1; i <= len; ++ i) printf("%d ", number[i]); puts("");
  ll pow10[15];
  pow10[0] = 1;
  for (int i = 1; i <= 14; ++i)
    pow10[i] = pow10[i - 1] * 10;
  // puts("da");
  int now = 0, nxt = 1;
  for (int i = 1; i <= len; ++i) {
    // printf("%d\\n", i);
    memset(f[nxt], 0, sizeof f[nxt]);
    for (int j = 0; j <= 9 * (len - i); ++j) {
      for (int k = 0; k < num; ++k) {

        for (int l = 0; l <= 2; ++l) {
          int maxn = number[i];
          for (int m = 0; m <= 9; ++m) {
            int status = go[k][m];
            // if (m < 2 && i == 2 && j == 0 && k == 0 && l == 1) printf("%d %d
            // %d\\n", j + m, maxn, l & (m == maxn));
            if (l == 1) {
              int flag = 1;
              if (m > maxn)
                flag = 2;
              else if (m < maxn)
                flag = 0;
              f[nxt][j][k][l] += f[now][j + m][status][flag];
            } else
              f[nxt][j][k][l] += f[now][j + m][status][l];
          }
        }
      }
    }
    swap(now, nxt);
  }
  // printf("%lld\\n", f[2][0][0][1]);
  // printf("%lld\\n", f[0][2][2][0]);
  // printf("%lld\\n", f[0][1][1][0]);
  // printf("%lld\\n", f[0][0][0][0]);
  printf("%lld\\n", f[now][0][0][1]);
}

Error: MLE

Fixed submission:

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <iostream>
#include <vector>

using namespace std;

struct data {
  int p;
  int s;
  int b;
  int c;
  int d;
  int e;
  int l;

  data() {}

  data(int _p, int _s, int _b, int _c, int _d, int _e, int _l) {
    p = _p; // pos
    s = _s; // sum
    b = _b; // pow2
    c = _c; // pow3
    d = _d; // pow5
    e = _e; // pow7
    l = _l; // less ou greater
  }
};

int tot[2], a[20], su[300][300], po[15][7];
char str[20];
bool vis[2][127][43][29][15][15][3];
// long long dp[2][127][43][29][15][15][3];
long long po2[43], po3[29], po5[15], po7[15], p10[20];
data f[2][1000000];
vector<vector<vector<vector<long long>>>> dp[2][127][15];

void add(int p, int s, int b, int c, int d, int e, int l) {
  if (vis[p][s][b][c][d][e][l]) {
    return;
  }
  /*if (tot[p] >= 1000000) {
      puts("ERROR");
      exit(0);
  }*/
  f[p][tot[p]++] = data(p, s, b, c, d, e, l);
  vis[p][s][b][c][d][e][l] = true;
}

int main() {

  for (int i = 0; i < 2; i++) {
    for (int j = 0; j < 127; j++) {
      for (int k = 0; k < 15; k++) {
        // 6
        int x = 14 - k;
        if (k * 6 > j) {
          continue;
        }
        dp[i][j][k] = vector<vector<vector<vector<long long>>>>(x + 1);
        for (int l = 0; l <= x; l++) {
          // 4 9
          if (k * 6 + l * 4 > j) {
            continue;
          }
          int y = (x - l) * 2;
          dp[i][j][k][l] = vector<vector<vector<long long>>>(y + 1);
          for (int q = 0; q <= y; q++) {
            // 2 5 8
            if (k * 6 + q + q > j || l * 4 + q + q > j) {
              continue;
            }
            int z = x + x + x;
            dp[i][j][k][l][q] = vector<vector<long long>>(z + 1);
            for (int p = 0; p <= z; p++) {
              // 1 3 5 7 9
              dp[i][j][k][l][q][p] = vector<long long>(3, 0);
            }
          }
        }
      }
    }
  }

  // return 0;

  p10[0] = 1;

  for (int i = 1; i <= 16; i++) {
    p10[i] = p10[i - 1] * 10;
  }

  po2[0] = po3[0] = po5[0] = po7[0] = 1;

  for (int i = 1; i < 43; i++) {
    po2[i] = po2[i - 1] * 2;
  }

  for (int i = 1; i < 29; i++) {
    po3[i] = po3[i - 1] * 3;
  }

  for (int i = 1; i < 15; i++) {
    po5[i] = po5[i - 1] * 5;
    po7[i] = po7[i - 1] * 7;
  }

  for (int i = 0; i < 300; i++) {
    for (int j = 0; j < 300; j++) {
      su[i][j] = i + j;
    }
  }

  for (int i = 0; i < 10; i++) {
    int x = i + 1;
    po[i][0] = po[i][1] = po[i][2] = po[i][3] = 0;
    while (x % 2 == 0) {
      po[i][0]++;
      x /= 2;
    }
    while (x % 3 == 0) {
      po[i][1]++;
      x /= 3;
    }
    while (x % 5 == 0) {
      po[i][2]++;
      x /= 5;
    }
    while (x % 7 == 0) {
      po[i][3]++;
      x /= 7;
    }
  }

  while (scanf("%s", str) != EOF) {
    int n = strlen(str);
    int sm = 0;
    int p2 = 0;
    int p3 = 0;
    int p5 = 0;
    int p7 = 0;
    long long pom = 1;
    double pre = clock();
    for (int i = 0; i < n; i++) {
      a[i] = str[i] - '0';
      int x = a[i];
      sm += a[i];
      pom *= x + 1;
    }
    long long ans = 0;
    tot[0] = tot[1] = 0;
    dp[0][0][0][0][0][0][1] = 1;
    add(0, 0, 0, 0, 0, 0, 1);
    for (int i = 1; i <= n; i++) {
      int q = i & 1;
      int p = 1 - q;
      int ch = str[i - 1] - '0';
      for (int j = 0; j < tot[p]; j++) {
        int s = f[p][j].s;
        int b = f[p][j].b;
        int c = f[p][j].c;
        int d = f[p][j].d;
        int e = f[p][j].e;
        int l = f[p][j].l;
        long long val = dp[p][s][e][d][c][b][l];
        if (s + 9 * (n - i + 1) < sm) {
          long long nval = val * p10[n - i + 1];
          ans += nval;
          continue;
        }
        // printf("dbg %d %d %d %d\\n", i, s, b, c);
        for (int k = 0; k < 10; k++) {
          int ss = su[s][k];
          int bb = su[b][po[k][0]];
          int cc = su[c][po[k][1]];
          int dd = su[d][po[k][2]];
          int ee = su[e][po[k][3]];
          if (ss > sm) {
            break;
          }
          long long sp = 1LL * po2[b] * po3[c] * po5[d] * po7[e];
          if (ss == sm && sp > pom) {
            continue;
          }
          // printf("deu pau %d\\n", k);
          /*if (dd >= dp[q][ss][bb][cc].size()) {
              printf("%d %d %d %d\\n", ss, bb, cc, dd);
              puts("sai");
              exit(0);
          }*/
          // printf("%d %d %d %d %d %d %d\\n", q, ss, ee, dd, cc, bb, l);
          /*if (dd >= dp[q][ss][ee].size()) {
              puts("saiu1");
              exit(0);
          } else if (cc >= dp[q][ss][ee][dd].size()) {
              puts("saiu2");
              exit(0);
          } else if (bb >= dp[q][ss][ee][dd][cc].size()) {
              printf("%d %d %d %d %d\\n", ss, ee, dd, cc, bb);
              puts("saiu3");
              exit(0);
          } else if (l >= dp[q][ss][ee][dd][cc][bb].size()) {
              puts("saiu4");
              exit(0);
          }*/
          if (l != 1) {
            dp[q][ss][ee][dd][cc][bb][l] += val;
            add(q, ss, bb, cc, dd, ee, l);
          } else if (k < ch) {
            dp[q][ss][ee][dd][cc][bb][0] += val;
            add(q, ss, bb, cc, dd, ee, 0);
          } else if (k == ch) {
            dp[q][ss][ee][dd][cc][bb][1] += val;
            add(q, ss, bb, cc, dd, ee, 1);
          } else {
            dp[q][ss][ee][dd][cc][bb][2] += val;
            add(q, ss, bb, cc, dd, ee, 2);
          }
        }
      }
      for (int j = 0; j < tot[p]; j++) {
        int s = f[p][j].s;
        int b = f[p][j].b;
        int c = f[p][j].c;
        int d = f[p][j].d;
        int e = f[p][j].e;
        int l = f[p][j].l;
        dp[p][s][e][d][c][b][l] = 0;
        vis[p][s][b][c][d][e][l] = false;
      }
      tot[p] = 0;
    }
    int p = (n & 1);
    // printf("%d\\n", tot[p]);
    for (int i = 0; i < tot[p]; i++) {
      int s = f[p][i].s;
      int b = f[p][i].b;
      int c = f[p][i].c;
      int d = f[p][i].d;
      int e = f[p][i].e;
      int l = f[p][i].l;
      // printf("%d %d %d %d %d %d %lld\\n", s, b, c, d, e, l,
      // dp[p][s][b][c][d][e][l]);
      if (s < sm) {
        ans += dp[p][s][e][d][c][b][l];
        // puts("--");
      } else if (s == sm) {
        long long sp = 1LL * po2[b] * po3[c] * po5[d] * po7[e];
        if (sp < pom) {
          ans += dp[p][s][e][d][c][b][l];
        } else if (sp == pom && l == 0) {
          ans += dp[p][s][e][d][c][b][l];
        }
      }
      dp[p][s][e][d][c][b][l] = 0;
      vis[p][s][b][c][d][e][l] = false;
    }
    tot[p] = 0;
    printf("%lld\\n", ans);
    // printf("%.10f\\n", clock() - pre);
  }

  return 0;
}