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

#include <algorithm>
#include <bitset>
#include <cmath>
#include <iostream>
#include <map>
#include <set>
#include <vector>
#define REP(i, s, n) for (int i = s; i < n; i++)
#define rep(i, n) REP(i, 0, n)
using namespace std;
typedef long long ll;
typedef pair<ll, int> P;
int N;
bool leading[27];
map<char, ll> coefficient;
map<P, int> cntbox; // first -> sum,second -> bit
map<ll, set<int>> cntbex;
int ans;
int S;

ll my_pow(ll a, ll e) {
  return !e ? 1 : (e % 2 ? a * my_pow(a, e - 1) : my_pow(a * a, e / 2));
}

ll getSum(vector<int> &toInt, vector<char> &alpha) {
  ll sum = 0;
  for (int i = 0; i < alpha.size(); i++)
    sum += toInt[i] * coefficient[alpha[i]];
  return sum;
}

void dfs(vector<int> &toInt, vector<char> &alpha, int pos, int used,
         bool flag) {

  if (pos >= toInt.size() && !flag) {
    ll sum = getSum(toInt, alpha);
    // cout << "xsum = " << sum << endl;
    cntbox[P(sum, used)]++;
    cntbex[sum].insert(used);
    return;
  } else if (pos >= toInt.size() && flag) {
    ll sum = getSum(toInt, alpha);
    // cout << "sum = " << sum << endl;
    /*
    for(map<P,int>::iterator it = cntbox.begin(); it != cntbox.end();it++)
      {
        if((*it).first.first + sum != 0)
          continue;

        int it_bit = (*it).first.second;
        bool ok = true;
        for(int i=0;i<10;i++)
          {
            if(((it_bit >> i) & 1) && ((used >> i) & 1))
              {
                ok = false;
                break;
              }
          }
        if(ok)
          {
            cout << "ok! " << (*it).first.first << endl;
            ans += (*it).second;
          }
      }
    */

    sum = -sum;
    // cntbex[sum].erase(unique(cntbex[sum].begin(),cntbex[sum].end()),cntbex[sum].end());
    set<int> dex = cntbex[sum];
    for (set<int>::iterator it = dex.begin(); it != dex.end(); it++) {
      int it_bit = (*it);
      bool ok = true;
      for (int j = 0; j < 10; j++) {
        if (((it_bit >> j) & 1) && ((used >> j) & 1)) {
          ok = false;
          break;
        }
      }
      if (ok) {
        // cout << "ok! " << sum << endl;
        ans += cntbox[P(sum, it_bit)];
      }
    }

    return;
  }

  for (int i = 0; i < 10; i++) {
    if (!i && leading[alpha[pos] - 'A'])
      continue;
    if ((used >> i) & 1)
      continue;
    toInt[pos] = i;
    dfs(toInt, alpha, pos + 1, used | (1 << i), flag);
  }
}

int main() {
  while (cin >> N, N) { // 半分全列挙
    ans = 0;
    coefficient.clear();
    cntbox.clear();
    cntbex.clear();
    vector<string> vec(N);
    set<char> al;
    int mex, mex2;
    mex = mex2 = 0;
    rep(i, 27) leading[i] = false;
    rep(i, N) {
      cin >> vec[i];
      if (i != N - 1)
        mex = max(mex, (int)vec[i].size());
      else
        mex2 = max(mex2, (int)vec[i].size());
      if (vec[i].size() != 1)
        leading[vec[i][0] - 'A'] = true;
      if (i != N - 1)
        rep(j, vec[i].size()) coefficient[vec[i][j]] +=
            my_pow(10, vec[i].size() - 1 - j),
            al.insert(vec[i][j]);
      else
        rep(j, vec[i].size()) coefficient[vec[i][j]] -=
            my_pow(10, vec[i].size() - 1 - j),
            al.insert(vec[i][j]);
    }
    // if(mex2 < mex || abs(mex2-mex) >= 2)
    //{
    // cout << 0 << endl;
    // continue;
    // }
    /*
    cout << "coefficient ---" << endl;
    for(map<char,ll>::iterator it = coefficient.begin(); it !=
    coefficient.end();it++) cout << (*it).second << "*" << (*it).first << " ";
    cout << endl;
    */
    int cn, sz;
    sz = S = al.size();
    cn = 0;
    vector<char> A, B;
    for (set<char>::iterator it = al.begin(); it != al.end(); it++) {
      if (cn < sz / 2)
        A.push_back((*it));
      else
        B.push_back((*it));
      cn++;
    }

    vector<int> toInt(A.size());
    dfs(toInt, A, 0, 0, false);
    toInt.resize(B.size());
    dfs(toInt, B, 0, 0, true);
    cout << ans << endl;
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cmath>
#include <deque>
#include <iostream>
#include <set>
#include <vector>
#define REP(i, s, n) for (int i = s; i < n; i++)
#define rep(i, n) REP(i, 0, n)
using namespace std;
int N;
int ans;
vector<string> vec;
bool leading[27];
int factorial[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800};

bool ok(vector<int> &toInt, vector<char> &alpha) {
  vector<string> line = vec;
  int alphas[27];
  rep(i, alpha.size()) alphas[alpha[i] - 'A'] = toInt[i];
  long long sum = 0;

  rep(i, vec.size()) {
    rep(j, vec[i].size()) {
      line[i][j] = (char)(alphas[vec[i][j] - 'A'] + '0');
    }
    if (i == vec.size() - 1) {
      if (sum == (atol)(line[i].c_str())) {
        /*
        cout << "sum = " << sum << endl;
        cout << "las = " << line[i] << endl;
        cout << "toInt ---" << endl;
        rep(k,toInt.size())
        cout << toInt[k] << " ";
        cout << endl;
        */
        return true;
      }
      // サンプルの最後が０になるのはリーディング０のカットで1桁のときの０もカットしてしまっているから
      return false;
    }
    sum += (atol)(line[i].c_str());
  }
  return false;
}

void dfs(vector<int> &toInt, vector<char> &alpha, int pos, int used, int one,
         int oi) {
  if (pos >= toInt.size()) {

    if (ok(toInt, alpha)) {
      /*
      cout << "reach" << endl;
      rep(i,toInt.size())
      {
        cout << alpha[i] << " -> " << toInt[i] << endl;
      }
      cout << endl;
      */

      if (one == 0)
        ans++;
      else
        ans += factorial[one];
    }
    return;
  }

  if (pos < one) {
    REP(i, oi, 10) {
      toInt[pos] = i;
      dfs(toInt, alpha, pos + 1, used | (1 << i), one, i + 1);
    }
    return;
  }

  rep(i, 10) {
    if (!i && leading[alpha[pos] - 'A'])
      continue;

    if ((used >> i) & 1)
      continue;
    toInt[pos] = i;
    dfs(toInt, alpha, pos + 1, used | (1 << i), one, oi);
  }
}

int main() {
  while (cin >> N, N) {
    ans = 0;
    vec.resize(N);
    vector<char> alphas;
    bool alpha[27];
    bool extra[27];
    rep(i, 27) alpha[i] = leading[i] = extra[i] = false;
    int mex, smex;
    mex = smex = 0;

    rep(i, N) {
      cin >> vec[i];
      if (i != N - 1)
        mex = max(mex, (int)vec[i].size());
      else
        smex = max(smex, (int)vec[i].size());
      if (vec[i].size() == 1 && !extra[vec[i][0] - 'A']) {
        extra[vec[i][0] - 'A'] = true;
        continue;
      }
      rep(j, vec[i].size()) alpha[vec[i][j] - 'A'] = true;
      if (vec[i].size() != 1)
        leading[vec[i][0] - 'A'] = true;
    }

    if (abs(mex - smex) >= 2 || mex > smex) {
      cout << 0 << endl;
      continue;
    }

    int one = 0;
    deque<int> deq;
    rep(i, 27) if (alpha[i]) deq.push_back((char)('A' + i));
    else if (extra[i]) deq.push_front((char)('A' + i)), one++;
    rep(i, deq.size()) alphas.push_back(deq[i]);
    vector<int> toInt(alphas.size());
    /*
    cout << "one = " << one << endl;
    rep(i,alphas.size())
    cout << alphas[i] << " ";
    cout << endl;
    */
    dfs(toInt, alphas, 0, 0, one, 0);

    cout << ans << endl;
  }
  return 0;
}