/// 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;
}
