using System;
using System.Numerics;
using System.Linq;
using System.Collections.Generic;
using System.Text;

namespace debug
{
    class main 
    {
        static void Main(string[] args)
        {
            //問題クラスを展開
            ProgramC a = new ProgramC();
            a.main();//実行する
            
        }

    }

    class ProgramA
    {
        public void main()
        {
            //入力
            string[] s = Console.ReadLine().Split(' ');
            int a = int.Parse(s[0]);
            int b = int.Parse(s[1]);

            //最大値出力
            Console.WriteLine(Math.Max(Math.Max(a * b, a - b), a + b));

        }


    }

    class ProgramB
    {
        public void main()
        {
            //入力
            string[] s = Console.ReadLine().Split(' ');
            int k = int.Parse(s[0]);
            int x = int.Parse(s[1]);


            for (int i = x - k + 1; i <= x + k -1 ; i++)
            {
                Console.Write(i);
                Console.Write(" ");

            }
            
        }

    }

    class ProgramC
    {
        public void main()
        {
            //入力
            string input = Console.ReadLine();
            int n = int.Parse(input);

            //辞書型で考える
            var dic = new Dictionary<string, int>();
            long sum = 0;
            //ちいさい順に並び変え
            for (int i = 0; i < n; i++)
            {
                string s = Console.ReadLine();
                char[] t = new char[10];
                for (int j = 0; j < 10; j++)
                    t[j] = s[j];

                Array.Sort(t);
                string sa = "";
                for (int j = 0; j < 10; j++)
                    sa += t[j];

                if (dic.ContainsKey(sa))//もしあるなら足す
                {
                    sum += dic[sa];
                    dic[sa]++;
                }
                else
                {
                    dic.Add(sa, 1);//それ以外では加える
                }

            }
            
            //答え出力
            Console.WriteLine(sum);
        }

    }

    class ProgramD
    {
        public void main()
        {
            string[] input = Console.ReadLine().Split(' ');

            int n = int.Parse(input[0]);
            int q = int.Parse(input[1]);
            List<Root> root = new List<Root>();
            List<Root> qes = new List<Root>();

            //親子を記録しておく
            for (int i = 0; i < n - 1; i++)
            {
                string[] t = Console.ReadLine().Split(' ');
                int a = int.Parse(t[0]);
                int b = int.Parse(t[1]);
                if(b < a)
                {
                    int te = b;
                    b = a;
                    a = te;
                }
                root.Add(new Root(a, b));
            }

            //お題を入れる
            for (int i = 0; i < q; i++)
            {
                string[] t = Console.ReadLine().Split(' ');
                int a = int.Parse(t[0]);
                int b = int.Parse(t[1]);
                qes.Add(new Root(a, b));
            }

            //お題と木の関係はソート
            var root_s = root.OrderBy(x => x.par);

            //答代入
            int[] cost = new int[n];

            //あらかじめ入れておく
            foreach (var s in qes)
                cost[s.par - 1] += s.child;
            //根の方から答えを入れていく（小さい順になる）
            foreach (var r in root_s)
                cost[r.child - 1] += cost[r.par - 1];

            //答
            for (int i = 0; i < n; i++)
                Console.WriteLine(cost[i]);

        }

    }

    public class Root
    {
        public int par;
        public int child;
        public Root(int par, int child)
        {
            this.par = par;
            this.child = child;
        }

    }



    class ProgramE
    {
        public void main()
        {
            //入力
            string s = Console.ReadLine();
            string t = Console.ReadLine();

            string s2 = s + s;//2つ足すことで奇数個しかない場合も、後ろの方に追加が単純になる

            long ans = 0;//ここに答えの位置を入れていく

            //あらかじめどういう文字列か把握する
            int[,] chart = new int[26, s.Length];
            //ないものを判定する
            for (int i = 0; i < s.Length; i++)
                for (int j = 0; j < 26; j++)
                    chart[j, i] = -1;
            //ある場合
            for(int i = 0;i < s2.Length;i++)
            {
                int c = s2[i] - 'a';
                //i番目より前を埋めていく
                for (int j = i; j >= 0; j--)
                {
                    if (j >= s.Length)
                    {
                        j = s.Length;//高速計算しないとダメ
                        continue;
                    }
                    //もし順序が与えられているならそれ以前は決まっている
                    if (chart[c, j] != -1)
                        break;
                    //和を足していく
                    chart[c, j] = i - j + 1;
                }

            }

            //tの文字列を貪欲法で探していく
            for (int i = 0;i < t.Length;i++)
            {
                int c = t[i] - 'a';
                if(chart[c, ans % s.Length] == -1)
                {
                    Console.WriteLine("-1");
                    return;
                }

                ans += chart[c, ans % s.Length];
            }

           

            //答え出力
            Console.WriteLine(ans);


        }

       

    }



}


Measured memory_bytes: 28424