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

#include <algorithm>
#include <iostream>
#include <map>
#include <set>
#include <string>
#include <vector>

#define REP(i, n) for (int i = 0; i < (int)(n); i++)

using namespace std;

int main() {
  int p10[10];
  int frac[10];
  p10[0] = 1;
  frac[0] = 1;
  REP(i, 9) p10[i + 1] = p10[i] * 10;
  REP(i, 9) frac[i + 1] = frac[i] * (i + 1);
  while (1) {
    int n;
    cin >> n;
    if (!n)
      break;
    vector<string> f(n);
    vector<char> abts;
    REP(i, n) {
      cin >> f[i];
      for (char c : f[i])
        if ('A' <= c && c <= 'Z')
          abts.push_back(c);
    }
    sort(begin(abts), end(abts));
    auto itr = unique(begin(abts), end(abts));
    abts.erase(itr, end(abts));
    int l = abts.size();
    vector<int> val(l);
    vector<bool> zeroable(l, true);
    REP(i, n) {
      int m = f[i].size();
      REP(j, m) {
        int k = find(begin(abts), end(abts), f[i][j]) - begin(abts);
        val[k] += p10[m - j - 1] * (i == (n - 1) ? -1 : 1);
        if (j == 0 && m > 1)
          zeroable[k] = false;
      }
    }
    vector<int> v(10);
    iota(begin(v), end(v), 0);
    int cnt = 0;
    do {
      int sum = 0;
      int ok = true;
      REP(i, l) {
        sum += val[i] * v[i];
        if (!zeroable[i] && v[i] == 0)
          ok = false;
      }
      if (sum == 0 && ok)
        ++cnt;
    } while (next_permutation(begin(v), end(v)));
    cout << (cnt / frac[10 - l]) << endl;
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <iostream>
#include <map>
#include <set>
#include <string>
#include <vector>

#define REP(i, n) for (int i = 0; i < (int)(n); i++)

using namespace std;

bool check(const vector<string> &f) {
  int sum = 0;
  for (auto &s : f) {
    if (s.size() > 1 && s.front() == '0')
      return false;
    sum += stoi(s);
  }
  return sum == stoi(f.back()) * 2;
}

bool prob_check(vector<string> f, const vector<int> &nums) {
  int mx = 0, mn = 9;
  REP(i, 10) if (nums[i]) {
    mx = max(mx, i);
    mn = min(mn, i);
  }
  int n = f.size();
  vector<string> mins = f;
  for (auto &s : mins)
    for (char &c : s)
      if ('A' <= c && c <= 'Z')
        c = mn + '0';
  for (auto &s : f)
    for (char &c : s)
      if ('A' <= c && c <= 'Z')
        c = mx + '0';
  int min_sum = 0;
  int max_sum = 0;
  REP(i, n - 1) {
    min_sum += stoi(mins[i]);
    max_sum += stoi(f[i]);
  }
  int rhs_min = stoi(mins.back());
  int rhs_max = stoi(f.back());
  return min_sum <= rhs_max && max_sum >= rhs_min;
}

int dfs(const vector<string> &f, const vector<int> &nums, vector<char> c) {
  if (c.empty()) {
    return check(f) ? 1 : 0;
  }
  if (!prob_check(f, nums))
    return 0;
  char x = c.back();
  c.pop_back();
  int sum = 0;
  REP(i, 10) {
    if (nums[i]) {
      auto cp = nums;
      auto cpf = f;
      cp[i] = 0;
      for (auto &s : cpf)
        for (char &y : s) {
          if (y == x)
            y = i + '0';
        }
      sum += dfs(cpf, cp, c);
    }
  }
  return sum;
}

int main() {
  while (1) {
    int n;
    cin >> n;
    if (!n)
      break;
    vector<string> f(n);
    REP(i, n) cin >> f[i];
    set<char> c;
    REP(i, n) for (char j : f[i]) c.insert(j);
    vector<char> v;
    for (char i : c)
      v.push_back(i);
    vector<int> num(10, 1);
    cout << dfs(f, num, v) << endl;
  }
  return 0;
}