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

#include <algorithm>
#include <iostream>
#include <map>
#include <math.h>
#include <stdio.h>
#include <string.h>

using namespace std;
typedef long long ll;
static const double EPS = 1e-9;
static const double PI = acos(-1.0);

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOREQ(i, s, n) for (int i = (s); i <= (int)(n); i++)
#define DEC(i, s) for (int i = (s); i >= 0; i--)

#define SIZE(v) (int)((v).size())
#define MEMSET(v, h) memset((v), h, sizeof(v))
#define FIND(m, w) ((m).find(w) != (m).end())

inline int bsf(int n) {
  int z;
  __asm__("bsf %1, %0;" : "=r"(z) : "r"(n));
  return z;
}

int n, m;
int mapto[256];
int len[100];
char str[100][20];
bool used[300];
bool cant0[10];
int lsum[10];
int rsum[10];

int calc(int use, int depth, int sum, int ans) {
  if (depth == m) {
    if (ans == sum) {
      return 1;
    }
    return 0;
  }
  int ret = 0;
  int v = ((1 << 10) - 1) ^ use;
  while (v) {
    int index = bsf(v);
    v -= v & -v;
    if (cant0[depth] && index == 0) {
      continue;
    }
    ans += rsum[depth] * index;
    sum += lsum[depth] * index;
    ret += calc(use | (1 << index), depth + 1, sum, ans);
    sum -= lsum[depth] * index;
    ans -= rsum[depth] * index;
  }
  return ret;
}

int main() {
  while (scanf("%d", &n), n) {
    REP(i, n) {
      scanf("%s", str[i]);
      len[i] = strlen(str[i]);
    }
    MEMSET(lsum, 0);
    MEMSET(rsum, 0);
    MEMSET(cant0, false);
    MEMSET(used, false);
    m = 0;
    REP(i, n) {
      int mul = pow(10, len[i] - 1);
      REP(j, len[i]) {
        if (!used[(int)str[i][j]]) {
          used[(int)str[i][j]] = true;
          mapto[(int)str[i][j]] = m;
          m++;
        }
        // str[i][j] = mapto[(int)str[i][j]];
        if (i != n - 1) {
          lsum[mapto[(int)str[i][j]]] += mul;
        } else {
          rsum[mapto[(int)str[i][j]]] += mul;
        }
        mul /= 10;
      }
      if (len[i] != 1) {
        cant0[mapto[(int)str[i][0]]] = true;
      }
    }
    printf("%d\\n", calc(0, 0, 0, 0));
  }
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <iostream>
#include <map>
#include <math.h>
#include <stdio.h>
#include <string.h>

using namespace std;
typedef long long ll;
static const double EPS = 1e-9;
static const double PI = acos(-1.0);

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOREQ(i, s, n) for (int i = (s); i <= (int)(n); i++)
#define DEC(i, s) for (int i = (s); i >= 0; i--)

#define SIZE(v) (int)((v).size())
#define MEMSET(v, h) memset((v), h, sizeof(v))
#define FIND(m, w) ((m).find(w) != (m).end())

inline int bsf(int n) {
  int z;
  __asm__("bsf %1, %0;" : "=r"(z) : "r"(n));
  return z;
}

int n, m;
int num[10];
int mapto[256];
int len[100];
char str[100][20];
bool used[300];
bool cant0[10];

int decode(int index) {
  int ret = 0;
  REP(i, len[index]) { ret = ret * 10 + num[(int)str[index][i]]; }
  return ret;
}

int calc(int use, int depth) {
  if (depth == m) {
    int ans = decode(n - 1);
    int sum = 0;
    REP(i, n - 1) {
      sum += decode(i);
      if (sum > ans) {
        return 0;
      }
    }
    if (ans != sum) {
      return 0;
    }
    return 1;
  }
  int ret = 0;
  int v = ((1 << 10) - 1) ^ use;
  while (v) {
    int index = bsf(v);
    v -= v & -v;
    num[depth] = index;
    if (cant0[depth] && index == 0) {
      continue;
    }
    ret += calc(use | (1 << index), depth + 1);
  }
  return ret;
}

int main() {
  while (scanf("%d", &n), n) {
    REP(i, n) {
      scanf("%s", str[i]);
      len[i] = strlen(str[i]);
    }
    MEMSET(cant0, false);
    MEMSET(used, false);
    m = 0;
    REP(i, n) {
      REP(j, len[i]) {
        if (!used[(int)str[i][j]]) {
          used[(int)str[i][j]] = true;
          mapto[(int)str[i][j]] = m;
          m++;
        }
        str[i][j] = mapto[(int)str[i][j]];
      }
      if (len[i] != 1) {
        cant0[(int)str[i][0]] = true;
      }
    }
    printf("%d\\n", calc(0, 0));
  }
}