#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<bitset>
#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;
}

Measured memory_bytes: 9420