Harryxun/sft_time huggingface dataset:
### BUGGY CODE ###

from math import gcd
if __name__ == "__main__":
    n = int(input())

    ans = 0
    for i in range(1, n+1):
        for j in range(1, n+1):
            for k in range(1, n+1):
                tmp = gcd(i, j)
                tmp = gcd(tmp, k)
                ans += tmp

    print(ans)


### FIXED CODE ###

from math import gcd
if __name__ == "__main__":
    n = int(input())

    ans = 0
    for i in range(1, n+1):
        for j in range(1, n+1):
            for k in range(1, n+1):
                tmp = gcd(i, j)
                tmp = gcd(tmp, k)
                ans += tmp

    print(ans)
### BUGGY CODE ###

if True:
    import math
    import fractions


    def make_prime_and_deleted_by_list(n):
        prime_list = [i for i in range(2, n+1)]
        deleted_by_list = [i for i in range(n+1)]
        pi = 0
        target_prime = prime_list[pi]
        while(target_prime < math.sqrt(n)):
            old_prime_list = prime_list.copy()
            prime_list = prime_list[:pi+1]
            for i in old_prime_list:
                if i % target_prime == 0:
                    deleted_by_list[i] = target_prime
                else:
                    if i > prime_list[pi]:
                        prime_list.append(i)
            pi += 1
            target_prime = prime_list[pi]
        return prime_list, deleted_by_list

    def make_factor_list(n, deleted_by_list, factor_list):
        if n == 1:
            return factor_list
        else:
            factor = deleted_by_list[n]
            factor_list.append(factor)
            return make_factor_list(int(n/factor), deleted_by_list, factor_list)

    def calc_gcd(As):
        ans = As[0]
        for i in range(1, len(As)):
            ans = fractions.gcd(ans, As[i])
        return ans
            
    N = int(input())
    As = list(map(int, input().split()))
    if As == [1 for i in range(N)]:
        print("pairwise coprime")
    else:
        _, d = make_prime_and_deleted_by_list(max(As))

        As_factor_list = []
        for A in As:
            As_factor_list.extend(set(make_factor_list(A, d, [])))

        if len(set(As_factor_list)) == len(As_factor_list):
            print("pairwise coprime")

        else:
            if calc_gcd(As) == 1:
                print("setwise coprime")
            else:
                print("not coprime")

### FIXED CODE ###

if True:
    N = int(input())
    As = list(map(int, input().split()))

    maxA = 10**6 + 6
    c = [0] * (maxA+1)
    for A in As:
        c[A] += 1
    isPrime = True
    cnt = 0
    for i in range(2, maxA+1):
        cnt = sum(c[i::i])
        if cnt == N:
            # Asはすべてiの約数
            print("not coprime")
            exit()
        if cnt >= 2:
            isPrime = False
        
    else:
        if isPrime:
            print("pairwise coprime")
        else:
            print("setwise coprime")
### BUGGY CODE ###

n,m=map(int,input().split());print(next(v for v in range(m//n,-1,-1)if m%v<1))

### FIXED CODE ###

#!/usr/bin/env python3
n, m = map(int, input().split())
print(next(v for v in range(m // n, -1, -1) if m % v == 0))
### BUGGY CODE ###

N = int(input())
ans = 1
for i in range(1,N + 1):
    ans = ans * i 

ans = ans % (10 ** 9 + 7)
print(ans)

### FIXED CODE ###

N = int(input())

ans = 1
mod = 10**9 + 7

for i in range(1, N + 1):
    ans = (ans * i) % mod

print(ans)
### BUGGY CODE ###

N = int(input())
A = [list(map(int, input().split())) for _ in range(N)]

L = []
for i in range(N):
  for j in range(i + 1, N):
    L.append([A[i][j], i, j])

ans = 0
for i in range(N - 1):
  for j in range(i + 1, N):
    for k in range(N):
      if i == k: continue
      if j == k: continue
      if A[i][j] > A[i][k] + A[k][j]:
        print(-1)
        exit()
      if A[i][j] == A[i][k] + A[k][j]:
        break
    else:
      ans += A[i][j]

print(ans)

### FIXED CODE ###

N = int(input())
A = [list(map(int, input().split())) for _ in range(N)]

L = []
for i in range(N):
  for j in range(i + 1, N):
    L.append([A[i][j], i, j])

ans = 0
for i in range(N - 1):
  for j in range(i + 1, N):
    for k in range(N):
      if i == k: continue
      if j == k: continue
      if A[i][j] > A[i][k] + A[k][j]:
        print(-1)
        exit()
      if A[i][j] == A[i][k] + A[k][j]:
        break
    else:
      ans += A[i][j]

print(ans)
### BUGGY CODE ###

#! /usr/bin/env python3

from fractions import gcd
from collections import Counter, deque, defaultdict
from heapq import heappush, heappop, heappushpop, heapify, heapreplace, merge
from bisect import bisect_left, bisect_right, bisect, insort_left, insort_right, insort
from itertools import accumulate, product, permutations, combinations, combinations_with_replacement

K = int(input())

ret = 0
for a in range(1, K+1):
    for b in range(1, K+1):
        n = gcd(a,b)
        for c in range(1,K+1):
            ret += gcd(n, c)
print(ret)

### FIXED CODE ###

from math import gcd
K = int(input())

ret = 0
for a in range(1, K+1):
    for b in range(1, K+1):
        n = gcd(a,b)
        for c in range(1,K+1):
            ret += gcd(n, c)
print(ret)
### BUGGY CODE ###

N,M,K=map(int,input().split())
*A,=map(int,input().split())
*B,=map(int,input().split())


AX=[0]*(N+1)
na=N+1
for i in range(1,N+1):
    AX[i]=AX[i-1]+A[i-1]
    if K<AX[i]:
        na=i
        break

BX=[0]*(M+1)
nb=M+1
for i in range(1,M+1):
    BX[i]=BX[i-1]+B[i-1]
    if K<BX[i]:
        nb=i
        break

ans=0
for i in range(na):
 for j in range(nb):
   if K < AX[i]+BX[j]:break
   ans=max(ans,i+j)
            
print(ans)

### FIXED CODE ###

N,M,K=map(int,input().split())
*A,=map(int,input().split())
*B,=map(int,input().split())

AX=[0]*(N+1)
na=N+1
for i in range(1,N+1):
    AX[i]=AX[i-1]+A[i-1]
    if K<AX[i]:na=min(na,i)

BX=[0]*(M+1)
nb=M+1
for i in range(1,M+1):
    BX[i]=BX[i-1]+B[i-1]
    if K<BX[i]:nb=min(nb,i)

import bisect        
ans=0
for i in range(na):
 j=bisect.bisect_right(BX,K-AX[i])-1
 # print(na,t,i,j)
 ans=max(ans,i+j)
            
print(ans)
### BUGGY CODE ###

n, m = map(int, input().split())
f_1 = []
t_n = []
jedge = 0
for i in range(m):
    a, b = map(int, input().split())
    if a == 1:
        f_1.append(b)
    if b == n:
        t_n.append(a)
for i in range(len(f_1)):
    for j in range(len(t_n)):
        if f_1[i] == t_n[j]:
            jedge = 1
            break
    if jedge == 1:
        break
if jedge == 1:
    print("POSSIBLE")
else:
    print("IMPOSSIBLE")


### FIXED CODE ###

import bisect

n, m = map(int, input().split())
f_1 = []
t_n = []
jedge = 0
for i in range(m):
    a, b = map(int, input().split())
    if a == 1:
        f_1.append(b)
    if b == n:
        t_n.append(a)
f_1.sort()
t_n.sort()
for i in range(len(f_1)):
    p = bisect.bisect_left(t_n, f_1[i])
    if p < len(t_n)-1 and f_1[i] == t_n[p]:
        jedge = 1
        break
    elif p == len(t_n)-1 and f_1[i] == t_n[p]:
        jedge = 1
        break
if jedge == 1:
    print("POSSIBLE")
else:
    print("IMPOSSIBLE")
### BUGGY CODE ###

n,k = map(int,input().split())
*l, = map(int,input().split())
seenl = [1]
temp=1
for i in range(k):
  temp=l[temp-1]
  if temp in set(seenl):
    lenloop = len(seenl)-seenl.index(temp)
    r = (k-i-1)%lenloop
    temp = seenl[seenl.index(temp):][r]
    break
  seenl.append(temp)
print(temp)

### FIXED CODE ###

n,k = map(int,input().split())
*l, = map(int,input().split())
seenl = [1]
seen = {1}
d={}
for index,i in enumerate(l):
  d[index+1]=i
#print(d)
temp=1
for i in range(k):
  temp=d[temp]
  if temp in seen:
    #print('i=',i)
    #print('temp=',temp)
    lenloop = len(seenl)-seenl.index(temp)
    #print('lenloop=',lenloop)
    r = (k-i-1)%lenloop
    temp = seenl[seenl.index(temp):][r]
    break
  seenl.append(temp)
  seen.add(temp)
print(temp)
### BUGGY CODE ###

n = int(input())
s = list(input())
passwd = set()
for i in range(1,n-1):
    pre = set(s[:i])
    post = set(s[i+1:])
    for c0 in pre:
        for c1 in post:
            passwd.add(c0+s[i]+c1)
print(len(passwd))

### FIXED CODE ###

import collections as col
n = int(input())
s = list(input())
passwd = set()
pre = col.Counter({'0':0,'1':0,'2':0,'3':0,'4':0,'5':0,'6':0,
                                '7':0,'8':0,'9':0})
post = col.Counter(s[1:])
for i in range(1,n-1):
    pre[s[i-1]] += 1
    post[s[i]] = max(0, post[s[i]]-1) 
    for c0 in pre:
        for c1 in post:
            if pre[c0] != 0 and post[c1] != 0:
                passwd.add(c0+s[i]+c1)
print(len(passwd))
### BUGGY CODE ###

#!/usr/bin/env python3
# encoding:utf-8
import copy
import random
import bisect #bisect_left　これで二部探索の大小検索が行える
import fractions #最小公倍数などはこっち
import math
import sys
import collections
from decimal import Decimal # 10進数で考慮できる

mod = 10**9+7
sys.setrecursionlimit(mod) # 再帰回数上限はでdefault1000

d = collections.deque()
def LI(): return list(map(int, sys.stdin.readline().split()))

N = int(input())

graph = [[mod for i in range(N)] for i in range(N)]

weights = {}

roots = [[] for i in range(N)]
for i in range(N - 1):
    a, b, c = LI()
    a -= 1
    b -= 1
    roots[a].append(b)
    roots[b].append(a)
    weights[(a,b)] = c
    weights[(b,a)] = c

Q, K = LI()
K -= 1
xy = [0 for i in range(Q)]
for i in range(Q):
    x, y = LI()
    x -= 1
    y -= 1
    xy[i] = [x, y]
"""
xyzで全部の通りを見つけるとN ** 3で無理
なので今回は木構造に注目してBFS or DFSで解いたらいいのでは？
"""

visited = [-1 for i in range(N)]
queue = collections.deque()
queue.append(K)
visited[K] = 0

while len(queue)> 0:
    node = queue.popleft()
    cnt = visited[node]
    for n_node in roots[node]:
        if visited[n_node] == -1:
            visited[n_node] = cnt + weights[(node, n_node)]
            queue.append(n_node)
for x, y in xy:
    print(visited[x] + visited[y])


### FIXED CODE ###

#!/usr/bin/env python3
# encoding:utf-8
import copy
import random
import bisect #bisect_left　これで二部探索の大小検索が行える
import fractions #最小公倍数などはこっち
import math
import sys
import collections
from decimal import Decimal # 10進数で考慮できる

mod = 10**9+7
sys.setrecursionlimit(mod) # 再帰回数上限はでdefault1000

d = collections.deque()
def LI(): return list(map(int, sys.stdin.readline().split()))

N = int(input())
weights = {}

roots = [[] for i in range(N)]
for i in range(N - 1):
    a, b, c = LI()
    a -= 1
    b -= 1
    roots[a].append(b)
    roots[b].append(a)
    weights[(a,b)] = c
    weights[(b,a)] = c

Q, K = LI()
K -= 1
xy = [0 for i in range(Q)]
for i in range(Q):
    x, y = LI()
    x -= 1
    y -= 1
    xy[i] = [x, y]
"""
xyzで全部の通りを見つけるとN ** 3で無理
なので今回は木構造に注目してBFS or DFSで解いたらいいのでは？
重みを単純にグラフに持つと10**5 ** 2になってしまうので注意
"""

visited = [-1 for i in range(N)]
queue = collections.deque()
queue.append(K)
visited[K] = 0

while len(queue)> 0:
    node = queue.popleft()
    cnt = visited[node]
    for n_node in roots[node]:
        if visited[n_node] == -1:
            visited[n_node] = cnt + weights[(node, n_node)]
            queue.append(n_node)

for x, y in xy:
    print(visited[x] + visited[y])
### BUGGY CODE ###

import itertools
import numpy as np 
n, m, k = map(int, input().split())
a = list(map(int, input().split()))
b = list(map(int, input().split()))
a = [0] + a
b = [0] + b
acc = list(itertools.accumulate(a))
bcc = list(itertools.accumulate(b))

acc = np.array(acc)
#print(acc)
bcc = np.array(bcc)

ans = 0

for i, val in enumerate(acc):
  if (val > k):
    break
  else:
    rest = k - val
    #print(rest)
    for j, val2 in enumerate(bcc):
      if (val2 <= rest):
        ans = max(ans, j + i)
      else:
        break

print(ans)
  


### FIXED CODE ###

import itertools
import numpy as np 
import sys
read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline
readlines = sys.stdin.buffer.readlines
# -------------------
n, m, k = map(int, readline().split())
#print(n)
a = list(map(int, readline().split()))
b = list(map(int, readline().split()))
a = [0] + a
b = [0] + b
acc = list(itertools.accumulate(a))
bcc = list(itertools.accumulate(b))

#acc = np.array(acc)
#print(acc)
#bcc = np.array(bcc)

ans = 0
j = m
for i, val in enumerate(acc):
  if (val > k):
    break
  else:
    rest = k - val
    #print(rest)
    #j = m
    #一ループ目がJの最大になるので、外側に置いてOK
    while (bcc[j] > rest):
      j -= 1

    ans = max(ans, j + i)


print(ans)
### BUGGY CODE ###

def main():
    from sys import stdin
    from collections import deque
    S = input()
    Q = int(input())
    reverse = 0
    head = []
    tail = []
    head_deque = deque(head)
    tail_deque = deque(tail)
    
    for _ in [0] * Q:
        readline = stdin.readline
        s = readline().split()
        if int(s[0]) == 1:
            if reverse == 1:
                reverse = 0
            else:
                reverse = 1
        else:
            if int(s[1]) == 1:
                if reverse == 1:
                    tail.append(s[2])
                else:
                    head_deque.appendleft(s[2])
                    head.insert(0, s[2])
            else:
                if reverse == 1:
                    head_deque.appendleft(s[2])
                else:
                    tail.append(s[2])
    head = list(head_deque)
    head = ''.join(head)
    tail = ''.join(tail)
    if reverse == 1:
        print(tail[::-1]+S[::-1]+head[::-1])
    else:
        print(head+S+tail)
        
main()

### FIXED CODE ###

def main():
    from sys import stdin
    from collections import deque
    S = input()
    Q = int(input())
    reverse = 0
    head = []
    tail = []
    head_deque = deque(head)
    tail_deque = deque(tail)
    
    for _ in [0] * Q:
        readline = stdin.readline
        s = readline().split()
        if int(s[0]) == 1:
            if reverse == 1:
                reverse = 0
            else:
                reverse = 1
        else:
            if int(s[1]) == 1:
                if reverse == 1:
                    tail.append(s[2])
                else:
                    head_deque.appendleft(s[2])
            else:
                if reverse == 1:
                    head_deque.appendleft(s[2])
                else:
                    tail.append(s[2])
    head = list(head_deque)
    head = ''.join(head)
    tail = ''.join(tail)
    if reverse == 1:
        print(tail[::-1]+S[::-1]+head[::-1])
    else:
        print(head+S+tail)
        
main()
### BUGGY CODE ###

# 毎回ソートすると間に合わん
# そもそも一番大きいやつは更新されないので、[b,c]についてcで降順ソートしたものを対象にする
# その時点で大きいものに更新されたやつは二度と更新されないので次回以降は省いたものだけ対象にできる
# orにぶたんでどこまでいけるか
import bisect

n, m = map(int, input().split())
arr = list(sorted(list(map(int, input().split()))))
bc = []
for _ in range(m):
    b, c = map(int, input().split())
    bc.append([b, c])

bc = list(sorted(bc, key=lambda x: x[1], reverse=True))
ans = 0

for bci in bc:
    d = bisect.bisect_left(arr, bci[1])
    arr = arr[min(d, bci[0]) :]
    ans += min(d, bci[0]) * bci[1]
print(ans + sum(arr))


### FIXED CODE ###

# 書き換える枚数は確定できる
# cの大きい順にしたものでaの小さい順にしたものを置き換えるイメージ
# なんか尺取っぽくなった

n, m = map(int, input().split())
arr = sorted(list(map(int, input().split())))

bcs = []
for _ in range(m):
    bc = list(map(int, input().split()))
    bcs.append(bc)

bcs = sorted(bcs, key=lambda x: x[1], reverse=True)
ans = 0

i = 0
for b in bcs:
    while i < n and arr[i] < b[1] and b[0] > 0:
        ans += b[1]
        b[0] -= 1
        i += 1
print(ans + sum(arr[i:]))
### BUGGY CODE ###

n,w = map(int, input().split())

item = []
for i in range(n):
    weight, value = map(int, input().split())
    item.append((weight, value))
item.sort()

max_value = [[0]*(w+1) for _ in range(n+1)]
for i in range(1, n+1):
    weight, value = item[i-1]
    for j in range(1, w+1):
        max_value[i][j] = max(max_value[i-1][j], max_value[i][j-1], max_value[i-1][j-weight] + value if j-weight >= 0 else 0)


print(max_value[n][w])

### FIXED CODE ###

n,w = map(int, input().split())
max_value = [[0]*(w+1) for _ in range(n+1)]
for i in range(1, n+1):
    weight, value = map(int, input().split())
    for j in range(1, weight):
        max_value[i][j] = max_value[i-1][j]
    for j in range(weight, w+1):
        max_value[i][j] = max(max_value[i-1][j], max_value[i-1][j-weight] + value)

print(max_value[n][w])
### BUGGY CODE ###

import math
#import numpy as np
import queue
from collections import deque,defaultdict
import heapq
from sys import stdin,setrecursionlimit
#from scipy.sparse.csgraph import dijkstra
#from scipy.sparse import csr_matrix
ipt = stdin.readline
setrecursionlimit(10**7)

def main():
    n = int(ipt())
    a = [int(i) for i in ipt().split()]
    b = [int(i) for i in ipt().split()]
    hq = []
    ans = 0
    for i,bi in enumerate(b):
        heapq.heappush(hq,(-bi,i))
    while len(hq) > 0:
        nbi,i = heapq.heappop(hq)
        if i < n-1:
            bp = b[i+1]
        else:
            bp = b[0]
        bm = b[i-1]
        if -nbi-bm-bp < a[i]:
            print(-1)
            exit()
        else:
            b[i] -= (bm+bp)
            if b[i] > a[i]:
                heapq.heappush(hq,(-b[i],i))
            ans += 1
    print(ans)
    return

if __name__ == '__main__':
    main()


### FIXED CODE ###

import math
#import numpy as np
import queue
from collections import deque,defaultdict
import heapq
from sys import stdin,setrecursionlimit
#from scipy.sparse.csgraph import dijkstra
#from scipy.sparse import csr_matrix
ipt = stdin.readline
setrecursionlimit(10**7)

def main():
    n = int(ipt())
    a = [int(i) for i in ipt().split()]
    b = [int(i) for i in ipt().split()]
    hq = []
    ans = 0
    for i,bi in enumerate(b):
        if bi > a[i]:
            heapq.heappush(hq,(-bi,i))
    while len(hq) > 0:
        #print(hq,b)
        nbi,i = heapq.heappop(hq)
        if i == n-1:
            bp = b[0]
        else:
            bp = b[i+1]
        bm = b[i-1]
        t = (-a[i]-nbi)//(bm+bp)
        if t == 0:
            print(-1)
            exit()
        b[i] -= (bm+bp)*t
        if b[i] > a[i]:
            heapq.heappush(hq,(-b[i],i))
        ans += t
    print(ans)
    return

if __name__ == '__main__':
    main()
### BUGGY CODE ###

def main():
    [n,k] = [int(i) for i in input().split()]
    h = [int(i) for i in input().split()]

    dp = [10 ** 10] * n
    dp[0] = 0
    dp[1] = abs(h[1] - h[0])
    for i in range(2,n):
      #ls = []
      m = 10 ** 9
      for j in range(1,k+1):
      	#ls.append(dp[i - j] + abs(h[i] - h[i - j]))
        m = min(dp[i - j] + abs(h[i] - h[i - j]),m)
        #dp[i] = min(ls)
        dp[i] = m
    print(dp[n-1])

if __name__ == '__main__':
    main()

### FIXED CODE ###

#import numpy
[n,k] = [int(i) for i in input().split()]
a = [int(i) for i in input().split()]
dp = [0]
i_ls = []
now = 0
#dpのi番目の要素がi+1番目の足場までの最小コスト
for i in range(1,n):
    #i番目の足場
    if i < k:
        for j in range(i):
            i_ls.append(abs(a[i]-a[j])+dp[j])
        #print("i<k")
    else:
        for j in range(i-k,i):
            i_ls.append(abs(a[i]-a[j])+dp[j])
        #print("i>=k")
    dp.append(min(i_ls))
    #print(i_ls)
    i_ls = []

print(dp[n-1])
### BUGGY CODE ###

import sys
def input(): return sys.stdin.readline().rstrip()
S = input()
Q = int(input())
rev = False
for _ in range(Q):
    q = input().split()
    if q[0] == '1':
        rev = not(rev)
    else:
        if (q[1]=='1' and rev is False) or (q[1]=='2' and rev is True):
            S = q[2] + S
        else:
            S = S + q[2]
print(S if rev == 0 else S[::-1])

### FIXED CODE ###

import sys
from collections import deque
def input(): return sys.stdin.readline().rstrip()
S = deque(input())
rev = False
apdlft = S.appendleft
apd = S.append

for _ in range(int(input())):
    q = input().split()
    if q[0] == '1':
        rev = not(rev)
    else:
        if (q[1]=='1' and rev is False) or (q[1]=='2' and rev is True):
            apdlft(q[2])
        else:
            apd(q[2])

if rev:
    print((''.join(S))[::-1])
else:
    print(''.join(S))
### BUGGY CODE ###

A,B,C,D=map(int,input().split())
def ans167(A,B,C,K):
    A_count=0
    B_count=0
    C_count=0
    for i in range(K):
        if A>0:
            A_count+=1
            A-=1
        elif B>0:
            B_count+=1
            B-=1
        else:
            C_count+=1
            C-=1
    return A_count-C_count
print(ans167(A,B,C,D))

### FIXED CODE ###

A,B,C,K=map(int,input().split())

def ans167(A, B, C, K):
    if A>=K:
        return(K)
    elif A+B>=K:
        return(A)
    else:
        return(A-(K-A-B))

print(ans167(A,B,C,K))
### BUGGY CODE ###

N = input()
As = list(map(int, input().split()))

result = 0
for i in range(len(As)-1):
    for j in range(i+1, len(As)):
        result+=As[i]*As[j]

print(result%(1*10**9+7))


### FIXED CODE ###

N = int(input())
As = list(map(int, input().split()))

result = 0
before_sum = sum(As)
for i in range(N-1):
    before_sum-=As[i]
    result+=As[i]*(before_sum)
print(result%(1*10**9+7))
### BUGGY CODE ###

import numpy as np

K = int(input())

K_list = [i+1 for i in range(K)]
res = 0

for i in range(len(K_list)):
  a = K_list[i]
  for j in range(len(K_list)):
    b = K_list[j]
    for k in range(len(K_list)):
      c = K_list[k]
      GCD = np.gcd.reduce([a, b, c])
      res += GCD

print(res)

### FIXED CODE ###

import math
K = int(input())

res = 0
for i in range(1, K+1):
  for j in range(1, K+1):
    gcd1 = math.gcd(i, j)
    for k in range(1, K+1):
      if gcd1 == 1:
        res += 1
      else:
        res += math.gcd(gcd1, k)
print(res)
### BUGGY CODE ###

n = int(input())
a = list(map(int,input().split()))

for i in range(n):
    print(a.index(i+1)+1," ",end="")
print()

### FIXED CODE ###

n = int(input())
a = list(map(int,input().split()))

ans = [0]*n
for i,num in enumerate(a):
    #print(a.index(i+1)+1," ",end="")
    ans[num-1] = i+1
for i in ans:
    print(i," ",end="")
### BUGGY CODE ###

N=int(input())
lst=[None]*N
for i in range(N):
    lst[i]=''.join(sorted(input()))
count=0
for i in range(N-1):
    for j in range(i+1, N):
        if lst[i]==lst[j]:
            count+=1
print(count)

### FIXED CODE ###

N=int(input())
lst=[None]*N
for i in range(N):
    lst[i]=''.join(sorted(input()))
count=0

import collections
dict=collections.Counter(lst)

for k, v in dict.items():
    count+=v*(v-1)//2

print(count)
### BUGGY CODE ###

from collections import defaultdict
class UnionFind:
    def __init__(self,nodes):
        self.parents = {node : node for node in nodes}
    def root(self,x):
        if x == self.parents[x]:
            return x
        else:
            rt = self.root(self.parents[x])
            self.parents[x] = rt
            return rt
    def find(self,x,y):
        return self.root(x) == self.root(y)
    def union(self,x,y):
        self.parents[self.root(x)] = self.root(y)
    def get_sets(self):
        res = defaultdict(list)
        for node, parent in self.parents.items():
            res[self.root(node)].append(node)
        # return [*res.values()]
        return list(res.values())

N,M = map(int,input().split(' '))
p = list(map(int,input().split(' ')))

uf = UnionFind(range(1,N+1))

for i in [0]*M:
    x, y = map(int,input().split(' '))
    uf.union(x,y)

sets = uf.get_sets()

ans = 0
for s in sets:
    for n in s:
        if uf.find(n,p[n-1]):
            ans += 1
print(ans)





### FIXED CODE ###

from collections import defaultdict
class UnionFind:
    def __init__(self,nodes):
        self.parents = {node : node for node in nodes}
    def root(self,x):
        if x == self.parents[x]:
            return x
        else:
            rt = self.root(self.parents[x])
            self.parents[x] = rt
            return rt
    def find(self,x,y):
        return self.root(x) == self.root(y)
    def union(self,x,y):
        self.parents[self.root(x)] = self.root(y)
    def get_sets(self):
        res = defaultdict(list)
        for node, parent in self.parents.items():
            res[self.root(node)].append(node)
        # return [*res.values()]
        return list(res.values())

N,M = map(int,input().split(' '))
p = list(map(int,input().split(' ')))

uf = UnionFind(range(1,N+1))

for i in [0]*M:
    x, y = map(int,input().split(' '))
    uf.union(x,y)

ans = 0
for n in range(1,N+1):
    if uf.find(n,p[n-1]):
        ans += 1
print(ans)