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

#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <map>
#include <memory.h>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <vector>
using namespace std;

#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define all(c) (c).begin(), (c).end()
#define iter(c) __typeof((c).begin())
#define pb(e) push_back(e)
#define foreach(c, i) for (iter(c) i = (c).begin(); i != c.end(); ++i)

typedef long long ll;
typedef pair<ll, ll> P;
const ll mod = 1000 * 1000 * 1000 + 7;
const double EPS = 1e-10;

const int maxn = 210;
const int sz = 1000;
ll p10[sz];
ll comb[maxn][maxn];
ll perm[maxn];
ll pattern[maxn];
vector<ll> card_size;
ll memo[maxn * maxn * maxn];

int digits(int n) {
  int res = 0;
  do {
    res++;
    n /= 10;
  } while (n > 0);
  return res;
}

ll recur(vector<ll> num) {

  if (*max_element(num.begin(), num.end()) == 0)
    return 1;

  ll h = 0;
  rep(i, num.size()) h = h * card_size[i] + num[i];

  if (memo[h] != -1)
    return memo[h];

  ll &res = memo[h] = 0;
  rep(i, num.size()) {
    if (num[i] > 0) {
      num[i]--;
      res = (res + recur(num) * (num[i] + 1)) % mod;
      num[i]++;
    }
  }
  return res;
}

ll pattern_num(const vector<ll> &rest) {
  int n = accumulate(rest.begin(), rest.end(), 0);
  return pattern[n];
}

ll dfs(vector<ll> cnt, const vector<ll> &num, ll sum, int c) {
  ll res = 0;
  if (c == (int)num.size()) {
    int len = 0;
    vector<ll> rest(cnt.size(), 0);
    rep(i, cnt.size()) {
      rest[i] = num[i] - cnt[i];
      len += cnt[i] * (i + 1);
    }

    ll p = recur(cnt) * pattern_num(rest) % mod;
    rep(i, cnt.size()) p = (p * comb[num[i]][cnt[i]]) % mod;
    p = (p * p10[len]) % mod;
    return sum * p % mod;
  }

  rep(i, num[c] + 1) {
    cnt[c] = i;
    res = (res + dfs(cnt, num, sum, c + 1)) % mod;
  }
  return res;
}

ll calc(vector<int> v) {
  vector<ll> sum(4, 0), cnt(4, 0), num(4, 0);

  rep(i, v.size()) {
    sum[digits(v[i]) - 1] += v[i];
    num[digits(v[i]) - 1]++;
  }

  memset(memo, -1, sizeof(memo));

  ll res = 0;
  card_size = num;
  rep(i, card_size.size()) card_size[i]++;
  rep(i, num.size()) {
    num[i]--;
    res = (res + dfs(cnt, num, sum[i], 0)) % mod;
    num[i]++;
  }
  return res;
}

void init() {
  p10[0] = 1;
  rep(i, sz - 1) p10[i + 1] = p10[i] * 10 % mod;
  rep(n, maxn) rep(r, maxn) {
    if (n < r)
      comb[n][r] = 0;
    else if (r == 0)
      comb[n][r] = 1;
    else
      comb[n][r] = (comb[n - 1][r] + comb[n - 1][r - 1]) % mod;
  }

  perm[0] = 1;
  rep(i, maxn - 1) perm[i + 1] = perm[i] * (i + 1) % mod;
  rep(i, maxn) {
    rep(j, i + 1) { pattern[i] = (pattern[i] + comb[i][j] * perm[j]) % mod; }
  }
}

int main() {
  int n, a;
  ll res = 0;
  vector<int> v;
  init();
  cin >> n;
  rep(i, n) {
    cin >> a;
    v.push_back(a);
  }
  sort(v.begin(), v.end());
  res = calc(v);
  if (v[0] == 0)
    res = (res + mod - calc(vector<int>(v.begin() + 1, v.end()))) % mod;
  cout << res << endl;
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <map>
#include <memory.h>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <vector>
using namespace std;

#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define all(c) (c).begin(), (c).end()
#define iter(c) __typeof((c).begin())
#define pb(e) push_back(e)
#define foreach(c, i) for (iter(c) i = (c).begin(); i != c.end(); ++i)

typedef long long ll;
typedef pair<ll, ll> P;
const ll mod = 1000 * 1000 * 1000 + 7;
const double EPS = 1e-10;

const int maxn = 210;
const int sz = 1000;
ll p10[sz];
ll comb[maxn][maxn];
ll perm[maxn];
ll pattern[maxn];
map<vector<ll>, ll> memo;

int digits(int n) {
  int res = 0;
  do {
    res++;
    n /= 10;
  } while (n > 0);
  return res;
}

ll recur(vector<ll> num) {
  if (*max_element(num.begin(), num.end()) == 0)
    return 1;
  if (memo.find(num) != memo.end())
    return memo[num];

  ll &res = memo[num] = 0;
  rep(i, num.size()) {
    if (num[i] > 0) {
      num[i]--;
      res = (res + recur(num) * (num[i] + 1)) % mod;
      num[i]++;
    }
  }
  return res;
}

ll pattern_num(const vector<ll> &rest) {
  int n = accumulate(rest.begin(), rest.end(), 0);
  return pattern[n];
}

ll dfs(vector<ll> cnt, const vector<ll> &num, ll sum, int c) {
  ll res = 0;
  if (c == (int)num.size()) {
    int len = 0;
    vector<ll> rest(cnt.size(), 0);
    rep(i, cnt.size()) {
      rest[i] = num[i] - cnt[i];
      len += cnt[i] * (i + 1);
    }

    ll p = recur(cnt) * pattern_num(rest) % mod;
    rep(i, cnt.size()) p = (p * comb[num[i]][cnt[i]]) % mod;
    p = (p * p10[len]) % mod;
    return sum * p % mod;
  }

  rep(i, num[c] + 1) {
    cnt[c] = i;
    res = (res + dfs(cnt, num, sum, c + 1)) % mod;
  }
  return res;
}

ll calc(vector<int> v) {
  vector<ll> sum(4, 0), cnt(4, 0), num(4, 0);

  rep(i, v.size()) {
    sum[digits(v[i]) - 1] += v[i];
    num[digits(v[i]) - 1]++;
  }
  memo.clear();
  ll res = 0;
  rep(i, num.size()) {
    num[i]--;
    res = (res + dfs(cnt, num, sum[i], 0)) % mod;
    num[i]++;
  }
  return res;
}

void init() {
  p10[0] = 1;
  rep(i, sz - 1) p10[i + 1] = p10[i] * 10 % mod;
  rep(n, maxn) rep(r, maxn) {
    if (n < r)
      comb[n][r] = 0;
    else if (r == 0)
      comb[n][r] = 1;
    else
      comb[n][r] = (comb[n - 1][r] + comb[n - 1][r - 1]) % mod;
  }

  perm[0] = 1;
  rep(i, maxn - 1) perm[i + 1] = perm[i] * (i + 1) % mod;
  rep(i, maxn) {
    rep(j, i + 1) { pattern[i] = (pattern[i] + comb[i][j] * perm[j]) % mod; }
  }
}

int main() {
  int n, a;
  ll res = 0;
  vector<int> v;
  init();
  cin >> n;
  rep(i, n) {
    cin >> a;
    v.push_back(a);
  }
  sort(v.begin(), v.end());
  res = calc(v);
  if (v[0] == 0)
    res = (res + mod - calc(vector<int>(v.begin() + 1, v.end()))) % mod;
  cout << res << endl;
  return 0;
}