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

#include <algorithm>
#include <cassert>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>

#define f first
#define s second
#define mp make_pair

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define rep(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOR(i, c)                                                              \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); i++)
#define ALL(c) (c).begin(), (c).end()
#define IN(x, s, g) ((x) >= (s) && (x) < (g))
#define ISIN(x, y, w, h) (IN((x), 0, (w)) && IN((y), 0, (h)))
#define print(x) printf("%d\\n", x)

using namespace std;

typedef unsigned int uint;
typedef long long ll;

const int _dx[] = {0, 1, 0, -1};
const int _dy[] = {-1, 0, 1, 0};

int getInt() {
  int ret = 0, c;
  c = getchar();
  while (!isdigit(c))
    c = getchar();
  while (isdigit(c)) {
    ret *= 10;
    ret += c - '0';
    c = getchar();
  }
  return ret;
}

int n;
char buff[13][10];
int len[13];
int enc[13][10];
bool zero[10];
int assign[10];
int cnttmp;
int cnt;

int check() {
  int sum = 0;
  REP(i, n) {
    int real = 0;
    REP(j, len[i]) {
      int tmp = enc[i][j];
      real *= 10;
      real += assign[tmp];
    }

    if (i == n - 1)
      sum -= real;
    else
      sum += real;
  }

  return sum == 0 ? 1 : 0;
}

bool check1() {
  int sum = 0;
  REP(i, n - 1) { sum += assign[enc[i][len[i] - 1]]; }
  return sum % 10 == assign[enc[n - 1][len[n - 1] - 1]];
}

int dfs(int flag, int rest) {
  if (rest == 0)
    return check();
  if (cnttmp == cnt - rest)
    if (!check1())
      return 0;
  int ret = 0;
  for (int i = (zero[cnt - rest] ? 0 : 1); i < 10; i++) {
    if ((flag & (1 << i)) != 0) {
      assign[cnt - rest] = i;
      ret += dfs(flag ^ (1 << i), rest - 1);
    }
  }
  return ret;
}

int main() {
  while (scanf("%d", &n), n) {
    int memo[256];
    cnt = 0;
    REP(i, 256) memo[i] = -1;
    REP(i, 10) zero[i] = true;
    REP(i, n) {
      scanf("%s", buff[i]);
      len[i] = strlen(buff[i]);
    }

    REP(jj, 13) {
      REP(i, n) if (jj < len[i]) {
        int j = len[i] - jj - 1;
        if (memo[buff[i][j]] == -1) {
          enc[i][j] = memo[buff[i][j]] = cnt++;
        } else {
          enc[i][j] = memo[buff[i][j]];
        }
        if (j == 0 && len[i] != 1)
          zero[enc[i][j]] = false;
      }
      if (jj == 0)
        cnttmp = cnt;
    }

    // REP(i,n) { REP(j,len[i]) printf("%d", enc[i][j]); puts(""); }

    printf("%d\\n", dfs((1 << 10) - 1, cnt));
  }

  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cassert>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>

#define f first
#define s second
#define mp make_pair

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define rep(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOR(i, c)                                                              \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); i++)
#define ALL(c) (c).begin(), (c).end()
#define IN(x, s, g) ((x) >= (s) && (x) < (g))
#define ISIN(x, y, w, h) (IN((x), 0, (w)) && IN((y), 0, (h)))
#define print(x) printf("%d\\n", x)

using namespace std;

typedef unsigned int uint;
typedef long long ll;

const int _dx[] = {0, 1, 0, -1};
const int _dy[] = {-1, 0, 1, 0};

int getInt() {
  int ret = 0, c;
  c = getchar();
  while (!isdigit(c))
    c = getchar();
  while (isdigit(c)) {
    ret *= 10;
    ret += c - '0';
    c = getchar();
  }
  return ret;
}

int n;
char buff[13][10];
int len[13];
int enc[13][10];
bool zero[10];
int assign[10];

int check() {
  int sum = 0;
  REP(i, n) {
    int real = 0;
    REP(j, len[i]) {
      int tmp = enc[i][j];
      real *= 10;
      real += assign[tmp];
    }

    if (i == n - 1)
      sum -= real;
    else
      sum += real;
  }

  return sum == 0 ? 1 : 0;
}

int dfs(int flag, int rest) {
  if (rest == 0)
    return check();
  int ret = 0;
  for (int i = (zero[rest - 1] ? 0 : 1); i < 10; i++) {
    if ((flag & (1 << i)) != 0) {
      assign[rest - 1] = i;
      ret += dfs(flag ^ (1 << i), rest - 1);
    }
  }
  return ret;
}

int main() {
  while (scanf("%d", &n), n) {
    int memo[256];
    int cnt = 0;
    REP(i, 256) memo[i] = -1;
    REP(i, 10) zero[i] = true;
    REP(i, n) {
      scanf("%s", buff[i]);
      len[i] = strlen(buff[i]);
      REP(j, len[i]) {
        if (memo[buff[i][j]] == -1) {
          enc[i][j] = memo[buff[i][j]] = cnt++;
        } else {
          enc[i][j] = memo[buff[i][j]];
        }
        if (j == 0 && len[i] != 1)
          zero[enc[i][j]] = false;
      }
    }
    printf("%d\\n", dfs((1 << 10) - 1, cnt));
  }

  return 0;
}