from heapq import heappush, heappop

from collections import deque,defaultdict,Counter

import itertools

from itertools import permutations

import sys

import bisect

import string

sys.setrecursionlimit(10**6)

def SI():

    return input().split()

def MI():

    return list(map(int,input().split()))

def I():

    return int(eval(input()))

def LI():

    return [int(i) for i in input().split()]

YN=['Yes','No']

YNeos='YNeos'

mo=10**9+7

imp='IMPOSSIBLE'

alp=string.ascii_lowercase

num=enumerate(alp)

d=dict()

for i,j in num:

    d[j]=i



n=I()

w=[]

ans=0

di=defaultdict(int)

X=[]

for i in range(n):

    s=''.join(sorted(list(eval(input()))))

    di[s]+=1

for i,j in list(di.items()):

    ans+=j*(j-1)//2

    

print(ans)
from heapq import heappush,heappop,heapify

from collections import deque,defaultdict,Counter

import itertools

from itertools import permutations,combinations

import sys

import bisect

import string

import math

import time

#import random

def I():

    return int(input())

def MI():

    return map(int,input().split())

def LI():

    return [int(i) for i in input().split()]

def LI_():

    return [int(i)-1 for i in input().split()]

def StoI():

    return [ord(i)-97 +10 for i in input()]

def ItoS(nn):

    return chr(nn+97)

def GI(V,E,Directed=False,index=0):

    org_inp=[]

    g=[[] for i in range(n)]

    for i in range(E):

        inp=LI()

        org_inp.append(inp)

        if index==0:

            inp[0]-=1

            inp[1]-=1

        if len(inp)==2:

            a,b=inp

            g[a].append(b)

            if not Directed:

                g[b].append(a)

        elif len(inp)==3:

            a,b,c=inp

            aa=(inp[0],inp[2])

            bb=(inp[1],inp[2])

            g[a].append(bb)

            if not Directed:

                g[b].append(aa)

    return g,org_inp

def show(*inp,end='\n'):

    if show_flg:

        print(*inp,end=end)

YN=['Yes','No']

mo=10**9+7

inf=float('inf')

l_alp=string.ascii_lowercase

u_alp=string.ascii_uppercase



#sys.setrecursionlimit(10**5)

input=lambda: sys.stdin.readline().rstrip()



show_flg=False

show_flg=True



n=I()

mp=defaultdict(int)

t=[]

for i in range(n):

    s=StoI()

    s.sort()

    tmp=0

    for i in s:

        tmp=tmp*100+i

    t.append(tmp)

    #mp[s]+=1

    

c=Counter(t)



ans=0

for i,j in c.items():

    ans+=j*(j-1)//2

print(ans)

from heapq import heappush, heappop
from collections import deque, defaultdict, Counter
import itertools
from itertools import permutations
import sys
import bisect
import string

sys.setrecursionlimit(10**6)


def SI():
    return input().split()


def MI():
    return list(map(int, input().split()))


def I():
    return int(eval(input()))


def LI():
    return [int(i) for i in input().split()]


YN = ["Yes", "No"]
YNeos = "YNeos"
mo = 10**9 + 7
imp = "IMPOSSIBLE"
alp = string.ascii_lowercase
num = enumerate(alp)
d = dict()
for i, j in num:
    d[j] = i
n = I()
w = []
ans = 0
di = defaultdict(int)
X = []
for i in range(n):
    s = "".join(sorted(list(eval(input()))))
    di[s] += 1
for i, j in list(di.items()):
    ans += j * (j - 1) // 2
print(ans)

from heapq import heappush, heappop, heapify
from collections import deque, defaultdict, Counter
import itertools
from itertools import permutations, combinations
import sys
import bisect
import string
import math
import time

# import random
def I():
    return int(input())


def MI():
    return map(int, input().split())


def LI():
    return [int(i) for i in input().split()]


def LI_():
    return [int(i) - 1 for i in input().split()]


def StoI():
    return [ord(i) - 97 + 10 for i in input()]


def ItoS(nn):
    return chr(nn + 97)


def GI(V, E, Directed=False, index=0):
    org_inp = []
    g = [[] for i in range(n)]
    for i in range(E):
        inp = LI()
        org_inp.append(inp)
        if index == 0:
            inp[0] -= 1
            inp[1] -= 1
        if len(inp) == 2:
            a, b = inp
            g[a].append(b)
            if not Directed:
                g[b].append(a)
        elif len(inp) == 3:
            a, b, c = inp
            aa = (inp[0], inp[2])
            bb = (inp[1], inp[2])
            g[a].append(bb)
            if not Directed:
                g[b].append(aa)
    return g, org_inp


def show(*inp, end="\n"):
    if show_flg:
        print(*inp, end=end)


YN = ["Yes", "No"]
mo = 10**9 + 7
inf = float("inf")
l_alp = string.ascii_lowercase
u_alp = string.ascii_uppercase
# sys.setrecursionlimit(10**5)
input = lambda: sys.stdin.readline().rstrip()
show_flg = False
show_flg = True
n = I()
mp = defaultdict(int)
t = []
for i in range(n):
    s = StoI()
    s.sort()
    tmp = 0
    for i in s:
        tmp = tmp * 100 + i
    t.append(tmp)
    # mp[s]+=1
c = Counter(t)
ans = 0
for i, j in c.items():
    ans += j * (j - 1) // 2
print(ans)

-from heapq import heappush, heappop +from heapq import heappush, heappop, heapify -from itertools import permutations +from itertools import permutations, combinations +import math +import time -sys.setrecursionlimit(10**6) - - -def SI(): -    return input().split() +# import random +def I(): +    return int(input()) -    return list(map(int, input().split())) - - -def I(): -    return int(eval(input())) +    return map(int, input().split()) +def LI_(): +    return [int(i) - 1 for i in input().split()] + + +def StoI(): +    return [ord(i) - 97 + 10 for i in input()] + + +def ItoS(nn): +    return chr(nn + 97) + + +def GI(V, E, Directed=False, index=0): +    org_inp = [] +    g = [[] for i in range(n)] +    for i in range(E): +        inp = LI() +        org_inp.append(inp) +        if index == 0: +            inp[0] -= 1 +            inp[1] -= 1 +        if len(inp) == 2: +            a, b = inp +            g[a].append(b) +            if not Directed: +                g[b].append(a) +        elif len(inp) == 3: +            a, b, c = inp +            aa = (inp[0], inp[2]) +            bb = (inp[1], inp[2]) +            g[a].append(bb) +            if not Directed: +                g[b].append(aa) +    return g, org_inp + + +def show(*inp, end="\n"): +    if show_flg: +        print(*inp, end=end) + + -YNeos = "YNeos" -imp = "IMPOSSIBLE" -alp = string.ascii_lowercase -num = enumerate(alp) -d = dict() -for i, j in num: -    d[j] = i +inf = float("inf") +l_alp = string.ascii_lowercase +u_alp = string.ascii_uppercase +# sys.setrecursionlimit(10**5) +input = lambda: sys.stdin.readline().rstrip() +show_flg = False +show_flg = True -w = [] +mp = defaultdict(int) +t = [] +for i in range(n): +    s = StoI() +    s.sort() +    tmp = 0 +    for i in s: +        tmp = tmp * 100 + i +    t.append(tmp) +    # mp[s]+=1 +c = Counter(t) -di = defaultdict(int) -X = [] -for i in range(n): -    s = "".join(sorted(list(eval(input())))) -    di[s] += 1 -for i, j in list(di.items()): +for i, j in c.items():