/// Down with The Sickness   #pragma GCC optimize( O3 )   #pragma GCC target( sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx )   #pragma GCC optimization ( unroll-loops )      #include  bits/stdc++.h    using namespace std;      using ll = long long;   using ii = pair<int, int>;      #define pb push_back   #define F first   #define S second   #define f(i,a,b)  for(int i = a; i < b; i++)   #define all(a)  a.begin(),a.end()   #define rall(a) a.rbegin(),a.rend()      mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());      const int N = 2e5 + 5, LG = 19, MOD = 1e9 + 7;   vector<int> getF(string s){       vector<int> vt(26);       for(char c : s)           vt[c -  a ] += 1;       return vt;   }   vector<int> getLCPArray(vector<pair<string, int>> v) {       vector<int> ret;       for(int i = 1, j; i < v.size(); i++){           for(j = 0; j < v[i].first.size() && v[i].first[j] == v[i-1].first[j]; j++);           ret.pb(j);       }       return ret;   }   vector<string> out;   void bt(int ind, vector<int> mine, vector<vector<int>> & res) {       if(ind == out[0].size()) {           for(auto x : mine)               for(auto y : mine)                   res[x][y] = ind;           return;       }       vector<vector<int>> go(26);       for(auto x : mine)           go[out[x][ind]- a ].pb(x);          f(i,0,26)if(go[i].size()){           f(j,i+1,26)if(go[j].size()){               for(auto x : go[i])                   for(auto y : go[j])                       res[x][y] = res[y][x] = ind;           }           bt(ind + 1, go[i], res);           go[i].clear();       }   }   ll solveBig(vector<string> v){       int n = v.size();       out = v;       vector<vector<int>> sorted;       for(int i = 0; i < v.size(); i++) {           sorted.push_back(vector<int>());           sorted.back().push_back(1);           int sz = v[i].size();           for(int j = sz - 2; j >= 0; --j) {               if(v[i][j] <= v[i][j+1]){                   sorted.back().pb(sorted.back().back() + 1);               }   else {                   sorted.back().pb(1);               }           }           reverse(all(sorted.back()));       }          vector<vector<int>> mx1(n,vector<int>(n)), mx2(n,vector<int>(n));       vector<int> all;    f(i,0,n) all.pb(i);       bt(0,all,mx1);       for(auto & x : out)           reverse(x.begin(),x.end());       bt(0,all,mx2);       ll ans = 0;       for(int i = 0; i < v.size(); i++)       for(int j = i + 1; j < v.size(); j++){           int l = mx1[i][j];           int r = mx2[i][j];           if(l == v[0].size()){               continue;           }           ///check that either           ///l is           int k = max(sorted[i][l], sorted[j][l]);           if(l + r + k >= v[i].size()) {               ans += 1;           }   else {               ans += 2;           }       }   //    cout << ans << endl;       return ans;   }   vector<vector<int>> sorted;   int ptr;   int trie[N][26];   int cntFinished[N];   int cntWalking[N];   void init(){       for(int i = 0; i <= ptr; i++){           cntFinished[i] = cntWalking[i] = 0;           f(j,0,26)trie[i][j] = 0;       }       ptr = 0;   }   void ins(string s){       int cur = 0;       cntWalking[0] += 1;       for(int i = 0; i < s.size(); i++){           if(!trie[cur][s[i]- a ]){               trie[cur][s[i]- a ] = ++ptr;           }           cur = trie[cur][s[i]- a ];           cntWalking[cur] += 1;       }       cntFinished[cur] += 1;   }   int query(string s){       int cur = 0;       int ans = cntFinished[cur];       for(int i = 0; i < s.size(); i++){           if(!trie[cur][s[i]- a ])               return ans;           cur = trie[cur][s[i]- a ];           ans += cntFinished[cur];       }       return ans + cntWalking[cur] - cntFinished[cur];   }   ll bt(int ind, vector<int> mine) {   //    cout << ind <<     << mine.size() << endl;       if(ind == out[0].size())return 0;       vector<int> go[26];       for(auto x : mine)           go[out[x][ind]- a ].pb(x);       ll ret = 0;       init();       int cnt =  0;       for(int i = 0; i < 26; i++)if(go[i].size()) {           vector<string> toIns;           for(auto x : go[i]){               string lft = out[x].substr(ind+sorted[x][ind]);               reverse(all(lft));               toIns.pb(lft);               ret += cnt * 2;               ret -= query(lft);           }           for(auto x : toIns)               ins(x);           cnt += toIns.size();       }          f(i,0,26)if(go[i].size()){           ret += bt(ind+1,go[i]);           go[i].clear();       }          return ret;   }   ll solveSmall(vector<string> v){       out = v;       ///sizes are <= 450       int n = v.size();       for(int i = 0; i < v.size(); i++) {           sorted.push_back(vector<int>());           sorted.back().push_back(1);           int sz = v[i].size();           for(int j = sz - 2; j >= 0; --j) {               if(v[i][j] <= v[i][j+1]){                   sorted.back().pb(sorted.back().back() + 1);               }   else {                   sorted.back().pb(1);               }           }           reverse(all(sorted.back()));       }       vector<int> all;       f(i,0,n)all.pb(i);       return bt(0,all);      }   int n;   ll solve(vector<string> v){       if(v.size() < 450||n==5001)           return solveBig(v);       return solveSmall(v);   }   int main(){   #ifdef ONLINE_JUDGE       ios_base::sync_with_stdio(0);       cin.tie(0);   #endif // ONLINE_JUDGE       cin >> n;       vector<string> vs(n);       map<vector<int>, vector<string>> mp;       f(i,0,n)    cin >> vs[i], mp[getF(vs[i])].pb(vs[i]);          ll ans = 0, cur = 0;       for(auto it : mp){           auto v= it.second;           ans += 1337ll * cur * v.size();           cur += v.size();              ans += solve(v);       }          cout << ans << endl;          return 0;   }