#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream> 
#include<algorithm>
#include<vector>
#include<string>
#include<map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn=2e5+10;
int n,len;
string str[maxn];
int lg[maxn];
struct longest_common_prefix{
	int height[maxn];
	vector<string> v;
	bool ___;
	void ddd(){ ___=true;}
	void set(vector<string> _v){ v=_v;}
	inline int _lcp(string a,string b){
		int ans=0;
		while(a[ans]==b[ans]) ans++;
		return ans;
	}
	void get_height(){
		for(int i=1;i<n;i++) height[i]=_lcp(v[i-1],v[i]);
	}
	int f[maxn][19];
	void init_st(){
		for(int i=0;i<n;i++) f[i][0]=height[i];
		int t=lg[n+1]+1;
		for(int j=1;j<t;j++)
			for(int i=0;i<=n-(1<<j);i++)
				f[i][j]=min(f[i][j-1],f[i+(1<<j-1)][j-1]);
	//	if(___) printf(">>>>%d<<<<",f[3][0]);
	}
	inline int query_st(int l,int r){
		
		int k=lg[r-l+1];
	//	if(___&&l==1&&r==3) printf("f[%d][%d] = %d, f[%d][%d] = %d<<<",l,k,f[l][k],r-(1<<k)+1,k,f[r-(1<<k)-1][k]);
		return min(f[l][k],f[r-(1<<k)+1][k]);
	}
	inline int lcp(int x,int y){
		if(x>y) swap(x,y);
		int tmp=query_st(x+1,y)-1; //printf("%d ",tmp);
//	if(___)	printf("lcp(%d, %d) = %d\n",x,y,tmp);
		return tmp;
	}
	void debug(){
		cout<<"height : "; for(int i=0;i<n;i++) cout<<height[i]<<" "; cout<<endl;
	}
}v1,v2;
int pos[maxn],pos_[maxn];
vector<int> s[maxn];
inline int lsp(int x,int y){
	int tmp=len-v2.lcp(pos[x],pos[y])-1;
//	printf("lsp(%d, %d) = %d\n",x,y,tmp);
	return tmp;
}
ll calc1(vector<string> v){
	ll ans=0;
	for(int i=1;i<n;i++)
		for(int j=0;j<i;j++){ 
			int p=v1.lcp(i,j),q=lsp(i,j);//puts("???");
		//	printf("(%d, %d) : p = %d, q = %d\n",i,j,p,q);
		//	printf("s[%d][%d] = %d, s[%d][%d] = %d\n",i,p+1,s[j][p+1],i,q-1,s[j][q-1]);
			if(s[j][p+1]==s[j][q-1]) ans+=1;
			else ans+=2;
		}
	return ans;
}
int mn[maxn],mx[maxn];
inline int findl(int p,int lcp_){
	int l=0,r=p;
	while(l<r){
		int mid=l+r>>1;
		if(v1.lcp(mid,p)>=lcp_) r=mid;
		else l=mid+1;
	}
	return l;
}
inline int findr(int p,int lcp_){
	int l=p,r=n-1;
	while(l<r){
		int mid=l+r+1>>1;
	//	printf("v1.lcp(%d, %d) = %d\n",mid,p,v1.lcp(mid,p));
		if(v1.lcp(mid,p)>=lcp_) l=mid;
		else r=mid-1;
	}
	return l;
}
inline int findl_(int p,int lsp_){
	int l=0,r=p;
	while(l<r){
		int mid=l+r>>1;
		if(len-v2.lcp(mid,p)-1<=lsp_) r=mid;
		else l=mid+1;
	}
	return l;
}
inline int findr_(int p,int lsp_){
	int l=p,r=n-1;
	while(l<r){
		int mid=l+r+1>>1;
		if(len-v2.lcp(mid,p)-1<=lsp_) l=mid;
		else r=mid-1;
	}
	return l;
}
struct SegTree{ int lc,rc,dat;}tr[maxn*4];
int rt[maxn],tot;
int build(int l,int r){
	int p=++tot;
	if(l==r) return tr[p].dat=tr[p].lc=tr[p].rc=0,p;
	int mid=l+r>>1;
	tr[p].lc=build(l,mid);
	tr[p].rc=build(mid+1,r);
	return p;
}
int modify(int now,int l,int r,int pos,int val){
	int p=++tot; tr[p]=tr[now];
	if(l==r) return tr[p].dat=val,p;
	int mid=l+r>>1;
	if(pos<=mid) tr[p].lc=modify(tr[now].lc,l,mid,pos,val);
	else tr[p].rc=modify(tr[now].rc,mid+1,r,pos,val);
	tr[p].dat=tr[tr[p].lc].dat+tr[tr[p].rc].dat;
	return p;
}
int ask(int p,int q,int l,int r,int ql,int qr){
	if(ql<=l&&qr>=r) return tr[q].dat-tr[p].dat;
	int mid=l+r>>1,res=0;
	if(ql<=mid) res=ask(tr[p].lc,tr[q].lc,l,mid,ql,qr);
	if(qr>mid) res+=ask(tr[p].rc,tr[q].rc,mid+1,r,ql,qr);
	return res;
}
ll calc2(vector<string> v){
	ll ans=0;
	for(int i=0;i<len-1;i++){
		for(int k=0;k<n;k++) mn[k]=mx[k]=v[k][i];
		for(int j=i+1;j<len;j++){
		//	printf("i = %d, j = %d\n",i,j);
			for(int k=0;k<n;k++){
				mn[k]=min(mn[k],(int)v[k][j]);
				mx[k]=max(mx[k],(int)v[k][j]);
			}
			tot=0; rt[0]=build(0,n);
			for(int k=0;k<n;k++) rt[k+1]=modify(rt[k],0,n,pos[k],s[k][i]==s[k][j]);
			for(int k=0;k<n;k++){
			//	if(i==0&&j==1) printf("%d %d %d %d\n",v[k][i],mn[k],v[k][j],mx[k]);
				if(v[k][i]==mn[k]||v[k][j]==mx[k]) continue;
				int l=findl(k,i-1),r=findr(k,i-1);
				int l_=findl_(pos[k],j+1),r_=findr_(pos[k],j+1);
			//	printf("k = %d : l = %d, r = %d, l_ = %d, r_ = %d\n",k,l,r,l_,r_);
			//	printf("ans += %d\n",l?ss[r]-ss[l-1]:ss[r]);
			//	ans+=l?ss[r]-ss[l-1]:ss[r];
				ans+=ask(rt[l],rt[r+1],0,n,l_,r_);
			//	printf("ask(%d, %d, %d, %d, %d, %d) = %d\n",l,r+1,0,n,l_,r_,ask(rt[l],rt[r+1],0,n,l_,r_));
			}
		//	exit(0);
		}
	}
	return (ll)n*(n-1)-ans;
}
ll calc(vector<string> v){
	n=v.size();
//	printf("n = %d, len = %d\n",n,len);
	sort(v.begin(),v.end());
	v1.set(v),v1.get_height(),v1.init_st();
	vector<string> rv=v;
	map<string,int> mp;
	for(int i=0;i<n;i++){
		reverse(rv[i].begin(),rv[i].end());
		mp[rv[i]]=i;
	}
	sort(rv.begin(),rv.end());
	for(int i=0;i<n;i++) pos[mp[rv[i]]]=i;
//	for(int i=0;i<n;i++) pos_[pos[i]]=i;
//	cout<<"pos : "; for(int i=0;i<n;i++) cout<<pos[i]<<" "; cout<<endl;
//	cout<<"pos_ : "; for(int i=0;i<n;i++) cout<<pos_[i]<<" "; cout<<endl;
 //v2.ddd();
 	v2.set(rv),v2.get_height(),v2.init_st();
/*	puts("v :");
	for(int i=0;i<n;i++) cout<<i<<" : "<<v[i]<<endl;
	puts("rv :");
	for(int i=0;i<n;i++) cout<<i<<" : "<<rv[i]<<endl;
	v2.debug();*/
	for(int i=0;i<n;i++){
		s[i].resize(len);
		s[i][0]=0;
		for(int j=1;j<len;j++)
			if(v[i][j]<v[i][j-1]) s[i][j]=s[i][j-1]+1;
			else s[i][j]=s[i][j-1];
	}
//	cout<<"s[0] : "; for(int i=0;i<len;i++) cout<<s[0][i]<<" "; cout<<endl;
	return n<=10000?calc1(v):calc2(v);
//return calc2(v);
}
int main(){
//	freopen("in.in","r",stdin);
	int n; cin>>n;
	for(int i=0;i<18;i++) lg[1<<i]=i;
	for(int i=3;i<=n+1;i++) if(!lg[i]) lg[i]=lg[i-1];
//	for(int i=0;i<maxn;i++) printf("lg[%d] = %d, ",i,lg[i]); puts("");
	map<vector<int>,vector<string> > mp;
	for(int i=1;i<=n;i++){
		cin>>str[i];
		vector<int> c(26);
		for(auto j:str[i]) c[j-'a']++;
		mp[c].push_back(str[i]);
	}
	len=str[1].length();
	int tot=0; ll ans=0;
	for(map<vector<int>,vector<string> >::iterator
			it=mp.begin();it!=mp.end();it++){
		ans+=calc(it->second);
		ans+=(ll)tot*it->second.size()*1337;
		tot+=it->second.size();
	}
	cout<<ans<<endl;
	return 0;
}
/*
6
abc
acb
bac
bca
cab
cba
*/
