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

#include <algorithm>
#include <cstdio>
#include <vector>

using namespace std;

const long long mod = 1000000007;

long long pw[1000];
long long sum[300];
long long fact[300];

void init() {
  pw[0] = 1;
  for (int i = 1; i < 1000; i++)
    pw[i] = (pw[i - 1] * 10) % mod;
  fact[0] = 1;
  for (int i = 1; i < 300; i++)
    fact[i] = (fact[i - 1] * i) % mod;
  for (int i = 0; i < 300; i++) {
    if (i == 0) {
      sum[i] = 1;
      continue;
    }
    long long tmp = 1;
    sum[i] = 1;
    for (int j = i; j >= 0; j--) {
      tmp = (tmp * j) % mod;
      sum[i] = (sum[i] + tmp) % mod;
    }
  }
}

int getDig(int n) {
  if (n == 0)
    return 1;
  int c = 0;
  while (n > 0) {
    n /= 10;
    c++;
  }
  return c;
}

vector<int> digs;
long long dp[2][201][801];

long long dp2[5][201][801];
bool checked[5];

long long solve(vector<int> vec) {
  long long res = 0;
  for (int i = 0; i < 5; i++)
    checked[i] = false;
  int N = vec.size();
  for (int i = 0; i < N; i++) {
    int k = getDig(vec[i]);
    int t = 0;
    if (checked[k])
      goto end_dp;
    checked[k] = true;
    digs.clear();
    for (int j = 0; j < N; j++) {
      if (i == j)
        continue;
      digs.push_back(getDig(vec[j]));
    }
    for (int a = 0; a <= 200; a++)
      for (int b = 0; b <= 800; b++)
        dp[0][a][b] = 0;
    dp[0][0][0] = 1;
    t = 0;
    for (int j = 0; j < N - 1; j++) {
      for (int a = 0; a <= 200; a++)
        for (int b = 0; b <= 800; b++)
          dp[1 - t][a][b] = 0;
      for (int a = 0; a <= 200; a++)
        for (int b = 0; b <= 800; b++) {
          dp[1 - t][a][b] += dp[t][a][b];
          if (a + 1 <= 200 && b + digs[j] <= 800) {
            dp[1 - t][a + 1][b + digs[j]] += dp[t][a][b];
          }
        }
      for (int a = 0; a <= 200; a++)
        for (int b = 0; b <= 800; b++) {
          dp[1 - t][a][b] %= mod;
        }
      t = 1 - t;
    }
    for (int a = 0; a <= 200; a++)
      for (int b = 0; b <= 800; b++)
        dp2[k][a][b] = dp[t][a][b];
  end_dp:;
    for (int a = 0; a <= 200; a++)
      for (int b = 0; b <= 800; b++) {
        int c = N - 1 - a;
        long long coe1 = sum[c];
        long long coe2 = pw[b];
        // long long coe3=dp[t][a][b];
        long long coe3 = dp2[k][a][b];
        long long tmp = (coe1 * coe2) % mod;
        tmp *= coe3;
        tmp %= mod;
        tmp *= fact[a];
        tmp %= mod;
        tmp *= vec[i];
        tmp %= mod;
        res = (res + tmp) % mod;
      }
  }
  return res;
}

int a[200];

int main() {
  init();
  int N;
  scanf("%d", &N);
  for (int i = 0; i < N; i++)
    scanf("%d", a + i);
  if (N == 1) {
    printf("%d\\n", a[0]);
    return 0;
  }
  long long ans = 0;
  vector<int> tmp1, tmp2;
  for (int i = 0; i < N; i++) {
    tmp1.push_back(a[i]);
    if (a[i] != 0)
      tmp2.push_back(a[i]);
  }
  ans = solve(tmp1);
  if (tmp1.size() != tmp2.size())
    ans -= solve(tmp2);
  ans %= mod;
  ans += mod;
  ans %= mod;
  printf("%lld\\n", ans);
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cstdio>
#include <vector>

using namespace std;

const long long mod = 1000000007;

long long pw[1000];
long long sum[300];
long long fact[300];

void init() {
  pw[0] = 1;
  for (int i = 1; i < 1000; i++)
    pw[i] = (pw[i - 1] * 10) % mod;
  fact[0] = 1;
  for (int i = 1; i < 300; i++)
    fact[i] = (fact[i - 1] * i) % mod;
  for (int i = 0; i < 300; i++) {
    if (i == 0) {
      sum[i] = 1;
      continue;
    }
    long long tmp = 1;
    sum[i] = 1;
    for (int j = i; j >= 0; j--) {
      tmp = (tmp * j) % mod;
      sum[i] = (sum[i] + tmp) % mod;
    }
  }
}

int getDig(int n) {
  if (n == 0)
    return 1;
  int c = 0;
  while (n > 0) {
    n /= 10;
    c++;
  }
  return c;
}

vector<int> digs;
long long dp[2][201][801];

long long solve(vector<int> vec) {
  long long res = 0;
  int N = vec.size();
  for (int i = 0; i < N; i++) {
    int x = vec[i];
    digs.clear();
    for (int j = 0; j < N; j++) {
      if (i == j)
        continue;
      digs.push_back(getDig(vec[j]));
    }
    for (int a = 0; a <= 200; a++)
      for (int b = 0; b <= 800; b++)
        dp[0][a][b] = 0;
    dp[0][0][0] = 1;
    int t = 0;
    for (int j = 0; j < N - 1; j++) {
      for (int a = 0; a <= 200; a++)
        for (int b = 0; b <= 800; b++)
          dp[1 - t][a][b] = 0;
      for (int a = 0; a <= 200; a++)
        for (int b = 0; b <= 800; b++) {
          dp[1 - t][a][b] += dp[t][a][b];
          if (a + 1 <= 200 && b + digs[j] <= 800) {
            dp[1 - t][a + 1][b + digs[j]] += dp[t][a][b];
          }
        }
      for (int a = 0; a <= 200; a++)
        for (int b = 0; b <= 800; b++) {
          dp[1 - t][a][b] %= mod;
        }
      t = 1 - t;
    }
    for (int a = 0; a <= 200; a++)
      for (int b = 0; b <= 800; b++) {
        int c = N - 1 - a;
        long long coe1 = sum[c];
        long long coe2 = pw[b];
        long long coe3 = dp[t][a][b];
        long long tmp = (coe1 * coe2) % mod;
        tmp *= coe3;
        tmp %= mod;
        tmp *= fact[a];
        tmp %= mod;
        tmp *= vec[i];
        tmp %= mod;
        res = (res + tmp) % mod;
      }
  }
  return res;
}

int a[200];

int main() {
  init();
  int N;
  scanf("%d", &N);
  for (int i = 0; i < N; i++)
    scanf("%d", a + i);
  if (N == 1) {
    printf("%d\\n", a[0]);
    return 0;
  }
  long long ans = 0;
  vector<int> tmp1, tmp2;
  for (int i = 0; i < N; i++) {
    tmp1.push_back(a[i]);
    if (a[i] != 0)
      tmp2.push_back(a[i]);
  }
  ans = solve(tmp1);
  if (tmp1.size() != tmp2.size())
    ans -= solve(tmp2);
  ans %= mod;
  ans += mod;
  ans %= mod;
  printf("%lld\\n", ans);
  return 0;
}