#include <bits/stdc++.h>
using namespace std;
struct big {
  vector<int> C;
  void kill0() {
    while (((int)(C).size()) > 1 && !C.back()) C.pop_back();
  }
  big(long long from = 0) {
    if (!from)
      C.push_back(0);
    else
      while (from) {
        C.push_back(from % 1000000000);
        from /= 1000000000;
      }
    kill0();
  }
  big(string from) {
    for (int i = ((int)(from).size()); i > 0; i -= 9)
      if (i - 9 >= 0)
        C.push_back(atoi(from.substr(i - 9, 9).c_str()));
      else
        C.push_back(atoi(from.substr(0, i).c_str()));
    kill0();
  }
  void out() {
    printf("%d", C.back());
    for (int i = ((int)(C).size()) - 2; i >= 0; --i) printf("%09d", C[i]);
  }
  bool operator<(const big& w) const {
    if (((int)(C).size()) != ((int)(w.C).size()))
      return ((int)(C).size()) < ((int)(w.C).size());
    for (int i = ((int)(C).size()) - 1; i >= 0; --i)
      if (C[i] != w.C[i]) return C[i] < w.C[i];
    return false;
  }
  bool operator==(const big& w) const {
    if (((int)(C).size()) != ((int)(w.C).size())) return false;
    for (int i = ((int)(C).size()) - 1; i >= 0; --i)
      if (C[i] != w.C[i]) return false;
    return true;
  }
  big operator+(big w) {
    big ret;
    ret = *this;
    int carry = 0;
    for (int i = 0;
         i < max(((int)(ret.C).size()), ((int)(w.C).size())) || carry; ++i) {
      if (i >= ((int)(ret.C).size())) ret.C.push_back(0);
      ret.C[i] += carry + ((i < ((int)(w.C).size())) ? w.C[i] : 0);
      carry = ret.C[i] >= 1000000000;
      if (carry) ret.C[i] -= 1000000000;
    }
    ret.kill0();
    return ret;
  }
  big operator-(big w) {
    big ret;
    ret = *this;
    int carry = 0;
    for (int i = 0; i < ((int)(ret.C).size()) || carry; ++i) {
      ret.C[i] -= carry + ((i < ((int)(w.C).size())) ? w.C[i] : 0);
      carry = ret.C[i] < 0;
      if (carry) ret.C[i] += 1000000000;
    }
    ret.kill0();
    return ret;
  }
  big operator*(big w) {
    big ret;
    ret.C.resize(((int)(C).size()) + ((int)(w.C).size()));
    for (int i = 0; i < ((int)(C).size()); ++i)
      for (int j = 0, carry = 0; j < ((int)(w.C).size()) || carry; ++j) {
        long long cur = ret.C[i + j] + carry +
                        C[i] * 1LL * (j < ((int)(w.C).size()) ? w.C[j] : 0);
        ret.C[i + j] = cur % 1000000000;
        carry = cur / 1000000000;
      }
    ret.kill0();
    return ret;
  }
  big operator/(big w) {
    big T = *this;
    int norm = 1000000000 / (w.C.back() + 1);
    T = T * norm;
    w = w * norm;
    big ret, tmp;
    ret.C.resize(((int)(T.C).size()), 0);
    for (int i = ((int)(T.C).size()) - 1; i >= 0; --i) {
      tmp = tmp * 1000000000 + T.C[i];
      int s1 = (((int)(tmp.C).size()) <= ((int)(w.C).size())
                    ? 0
                    : tmp.C[((int)(w.C).size())]);
      int s2 = (((int)(tmp.C).size()) < ((int)(w.C).size())
                    ? 0
                    : tmp.C[((int)(w.C).size()) - 1]);
      int koef = (s1 * 1LL * 1000000000 + s2) / (w.C.back());
      while (tmp < w * koef) --koef;
      tmp = tmp - w * koef;
      ret.C[i] = koef;
    }
    ret.kill0();
    return ret;
  }
  void operator*=(int w) {
    int carry = 0;
    for (int i = 0; i < ((int)(C).size()) || carry; ++i) {
      if (i >= ((int)(C).size())) C.push_back(0);
      long long cur = C[i] * 1LL * w + carry;
      C[i] = cur % 1000000000;
      carry = cur / 1000000000;
    }
    kill0();
  }
  void operator/=(int w) {
    int carry = 0;
    for (int i = ((int)(C).size()) - 1; i >= 0; --i) {
      long long cur = C[i] + carry * 1LL * 1000000000;
      C[i] = cur / w;
      carry = cur % w;
    }
    kill0();
  }
};
big ans = 1;
char buf[100010];
set<char> used;
vector<char> avb;
int main() {
  scanf("%s", &buf);
  string S(buf);
  int po10 = 0;
  for (int i = 0; i < ((int)(S).size()); ++i) {
    if (S[i] == '?') {
      if (i == 0)
        ans *= 9;
      else
        ++po10;
      continue;
    }
    if (S[i] >= '0' && S[i] <= '9') continue;
    if (used.count(S[i])) continue;
    used.insert(S[i]);
    avb.push_back(S[i]);
  }
  for (int i = 0; i < ((int)(avb).size()); ++i) {
    int mult = 10 - i;
    if (i == 0 && S[0] == avb[i]) --mult;
    (mult) = max((mult), (0));
    ans *= mult;
  }
  ans.out();
  while (po10 > 0) --po10, printf("0");
  puts("");
  return 0;
}
