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

N = int(input())

for h in range(1, 3501):
  for n in range(1, 3501):
    a = (4 * h * n) - N * h - N * n
    if a == 0:
      continue
    w = (N * h * n) / a
    if w.is_integer() and 0 < w:
      print(h, n, int(w))
      exit(0)

### FIXED CODE ###

N = int(input())

for h in range(1, 3501):
  for n in range(1, 3501):
    a = (4 * h * n) - N * h - N * n
    if a <= 0:
      continue
    w = (N * h * n) / a
    if w.is_integer() and 0 < w:
      print(h, n, int(w))
      exit(0)
### BUGGY CODE ###

import sys
input = sys.stdin.readline
sys.setrecursionlimit(10**6)


def main():

    n = int(input())
    s = list(input())
    q = int(input())
    for i in range(q):
        a, b, c = map(str, input().split())
        if a == '1':
            s[int(b)-1] = c
        else:
            p = s[int(b)-1:int(c)]
            print(len(set(p)))


main()


### FIXED CODE ###

import sys
import bisect
input = sys.stdin.readline
sys.setrecursionlimit(10**6)


def main():

    n = int(input())
    s = list(input().strip())
    q = int(input())
    alpha = g = [[] for _ in range(26)]
    orda = ord('a')
    for i in range(n):
        alpha[ord(s[i])-orda].append(i)
    for i in range(q):
        a, b, c = map(str, input().split())
        if a == '1':
            b = int(b)-1
            if c != s[b]:
                alpha[ord(s[b])-orda].remove(b)
                s[b] = c
                bisect.insort(alpha[ord(c)-orda], b)
        else:
            ans = 0
            for i in range(26):
                if len(alpha[i]) > 0:
                    it = bisect.bisect_left(alpha[i], int(b)-1)
                    if it < len(alpha[i]) and alpha[i][it] < int(c):
                        ans += 1
            print(ans)


main()
### BUGGY CODE ###

n, m = map(int, input().split())
a = [0]*m
for i in range(m):
  a[i] = int(input())


r1 = 1
if 1 in a:
  r = 0
else:
  r = 1
for i in range(2, n+1):
  r2 = r1
  r1 = r
  if i in a:
    r = 0
  else:
    r = r1 + r2

print(r%1000000007)

### FIXED CODE ###

n, m = map(int, input().split())
a = [0]*m
for i in range(m):
  a[i] = int(input())

up = [0]*(m+1)
if m == 0:
  up[0] = n
else:
  up[0] = a[0]-1
  up[m] = n - a[m-1]-1
  for i in range(m-1):
    up[i+1] = a[i+1]-a[i]-2

ans = 1
if -1 in up:
  ans = 0
else:
  f = [0]*(max(up)+1)
  f[0] = 1
  if max(up) > 0:
    f[1] = 1
    for i in range(2, max(up)+1):
      f[i] = f[i-1] + f[i-2]
  for i in range(m+1):
    ans *= f[up[i]]

print(ans % 1000000007)
### BUGGY CODE ###

import sys
input = sys.stdin.readline
mod = 10**9 + 7

s = input().rstrip()
n = len(s)
s = s[::-1]

dp = [[0]*13 for _ in range(n + 1)] # dp[i][j] : i桁目まで見て13で割ってj余る個数
dp[0][0] = 1
for i in range(n):
    if s[i] != '?':
        s_ = int(s[i]) * 10**i
        for j in range(13):
            dp[i + 1][(j + s_) % 13] += dp[i][j]
            dp[i + 1][(j + s_) % 13] %= mod
    else:
        for j in range(13):
            for k in range(10):
                k *= 10**i
                dp[i + 1][(j + k) % 13] += dp[i][j]
                dp[i + 1][(j + k) % 13] %= mod
print(dp[-1][5])



### FIXED CODE ###

def main():
    MOD = 7 + 10**9
    S = tuple(input())
    N = len(S)
    dp = [[0]*13 for _ in range(N+1)]
    dp[0][0] += 1
    s=[1]
    for n in range(1,N):
        s.append((s[n-1]*10)%13)
    for i in range(N):
        for k in range(13):
            if S[-(i+1)] != '?':
                dp[i+1][(k+int(S[-(i+1)])*s[i])%13] += dp[i][k] 
                dp[i+1][(k+int(S[-(i+1)])*s[i])%13] %= MOD
            else:
                for l in range(10):
                    dp[i+1][(k+l*s[i])%13] += dp[i][k]
                    dp[i+1][(k+l*s[i])%13] %= MOD
    print(dp[-1][5])

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

from sys import stdin
from collections import defaultdict as dd
from collections import deque as dq
import itertools as it
from math import sqrt, log, log2
from fractions import Fraction

n, k = map(int, input().split())
intensity = list(map(int, stdin.readline().split()))

count = 0
while count < k:
    totsum = 0
    prefs = [0]*n
    zeros = []
    for i in range(n):
        if intensity[i]!=0:
            l = i - intensity[i]
            r = i + intensity[i] + 1

            prefs[max(l, 0)] += 1
            if r <= n-1: 
                prefs[r] += -1
        else:
            zeros.append(i)
            
    for i in range(1, n):
        prefs[i] += prefs[i-1]
        totsum += prefs[i]
    
    for i in zeros:
        if intensity[i] == 0:
            prefs[i] += 1
            totsum += 1
    
    if totsum == n*n:
        print(*prefs)
        exit()
    
    intensity = prefs
    count += 1

print(*prefs)

### FIXED CODE ###

from sys import stdin
# from collections import defaultdict as dd
# from collections import deque as dq
# import itertools as it
# from math import sqrt, log, log2
# from fractions import Fraction

n, k = map(int, input().split())
intensity = list(map(int, stdin.readline().split()))

count = 0
while count < k:
    totsum = 0
    prefs = [0]*n
    zeros = []
    for i in range(n):
        l = i - intensity[i]
        r = i + intensity[i] + 1

        prefs[max(l, 0)] += 1
        if r <= n-1: 
            prefs[r] += -1
            
    for i in range(1, n):
        prefs[i] += prefs[i-1]
        totsum += prefs[i]
    
    if sum(prefs) == n*n:
        print(*prefs)
        exit()
    
    intensity = prefs
    count += 1

print(*prefs)
### BUGGY CODE ###

# python には結構厳しいTLE・・・python以外のお勉強時間ないよ～( ;∀;)
# . から見た # の最大距離の方が楽ではあるが・・・
H, W = list(map(int, input().split()))
L = [[True if j == "#" else False for j in input()] for i in range(H)]
blacks = [[i, j] for i in range(H) for j in range(W) if L[i][j]]
black_count = len(blacks)

cands = [[-1, 0], [1, 0], [0, -1], [0, 1]]
all_count = H * W
result = 0
while black_count < all_count:
  next_steps = list(set([(black[0]+cand[0], black[1]+cand[1]) for black in blacks for cand in cands]))
  next_blacks = [[i,j] for i, j in next_steps if i >= 0 and i < H and j >= 0 and j < W and not L[i][j]]
  for i, j in next_blacks:
    L[i][j] = True
  black_count += len(next_blacks)
  blacks = next_blacks
  result += 1

print(result)


### FIXED CODE ###

# python には結構厳しいTLE・・・python以外のお勉強時間ないよ～( ;∀;)
# . から見た # の最大距離の方が楽ではあるが・・・
# 嫌いだけど def main も使ってみた．
from collections import deque
import copy

def main():
  H, W = list(map(int, input().split()))
  L = [[j=="#" for j in input()] for i in range(H)]
  q = deque([(i, j) for i in range(H) for j in range(W) if L[i][j]])
  cands = [(0, -1), (0, 1), (-1, 0), (1, 0)]
  result = 0
  while True:
    nq = deque()
    while q:
      i, j = q.popleft()
      if i > 0 and not L[i-1][j]:
        L[i-1][j] = True
        nq.append((i-1, j))
      if j > 0 and not L[i][j-1]:
        L[i][j-1] = True
        nq.append((i, j-1))
      if i < H-1 and not L[i+1][j]:
        L[i+1][j] = True
        nq.append((i+1, j))
      if j < W-1 and not L[i][j+1]:
        L[i][j+1] = True
        nq.append((i, j+1))
    if nq:
      q = copy.copy(nq)
    else:
      break    
    result += 1
  print(result)

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

s = input()
ans = 0
f = 0
while f == 0:
  if 'BW' in s:
    a = s.index('BW')
    s = s[:a] + 'WB' + s[a + 2:]
    ans += 1
  else:
    f == 1
    break
print(ans)

### FIXED CODE ###

s = input()
ans = 0
w = 0
for i in range(len(s)):
  if s[i] == 'W':
    ans += i - w
    w += 1
print(ans)
### BUGGY CODE ###

x = int(input())
for a in range(1000000000000000):
  for b in range(1000000000000000):
    if a ** 5 - b ** 5 == x:
      print(str(a)+" "+str(b))
    

### FIXED CODE ###

x = int(input())
import sys
for a in range(1000):
  for b in range(1000):
    if (a ** 5 - b ** 5) == x:
      print(str(a)+" "+str(b))
      sys.exit()
    elif(a ** 5 - (-b) ** 5) == x:
      print(str(a)+" "+str(-b))
      sys.exit()
    elif((-a) ** 5 - b ** 5) == x:
      print(str(-a)+" "+str(b))
      sys.exit()
    elif((-a) ** 5 - (-b) ** 5) == x:
      print(str(-a)+" "+str(-b))
      sys.exit()
### BUGGY CODE ###

class BIT:
    """1-indexed BIT
    """

    def __init__(self, size: int):
        """サイズを指定して BIT を初期化します。
        """
        self.__size = size
        self.__bit = [0] * (self.__size+1)

    def add(self, idx: int, val: int):
        """位置 idx (1-indexed) に値 val をたす。
        :param idx: 値を追加したいインデックス
        :param val: 追加したい値
        """
        while idx <= self.__size:
            self.__bit[idx] += val
            idx += idx & (-idx)

    def sum(self, l: int, r: int)->int:
        """(l, r] の累積和を計算する。
        :param l: left index
        :param r: right index
        :return: (l, r] の累積和
        """
        return self.__sum__(r) - self.__sum__(l)

    def __sum__(self, idx: int)->int:
        s = 0
        while idx > 0:
            s += self.__bit[idx]
            idx -= idx & (-idx)
        return s


def inversion(A: list) -> int:
    bit = BIT(max(A))
    s = 0
    for a in A:
        s += bit.sum(0, a)
        bit.add(a, 1)

    return s


def check2(A: list, x: int)->int:
    n = len(A)
    S = [0] * (n + 1)
    for i in range(n):
        if x <= A[i]:
            S[i + 1] = S[i] + 1
        else:
            S[i + 1] = S[i] - 1

    m = min(S)
    return inversion([s - (m - 1) for s in S])


def median_of_medians(N: int, A: list) -> int:
    def check(x: int)->int:
        S = [0] * (N + 1)
        for i in range(N):
            if x <= A[i]:
                S[i + 1] = S[i] + 1
            else:
                S[i + 1] = S[i] - 1

        m = min(S)
        for i in range(N + 1):
            S[i] -= m - 1

        bit = BIT(max(S))
        s = 0
        for a in S:
            s += bit.sum(0, a)
            bit.add(a, 1)

        return s

    alpha = sorted(A)
    l, r = 0, N
    while r - l > 1:
        m = (r + l + 1) // 2
        if 2*check(alpha[m]) >= (N * (N + 1)) // 2:
            l = m
        else:
            r = m

    return alpha[l]


if __name__ == "__main__":
    N = int(input())
    A = [int(s) for s in input().split()]
    ans = median_of_medians(N, A)
    print(ans)


### FIXED CODE ###


def median_of_medians(N: int, A: list)->int:
    def search(c):
        bar = N
        r = 0
        res_nega = 0
        dp_arr = [0]*(2*N+1)
        for i in range(N):
            dp_arr[bar] += 1
            if A[i] < c:
                r += dp_arr[bar]
                bar += 1
            else:
                r -= (dp_arr[bar-1])
                bar -= 1
            res_nega += r
        return res_nega

    # binary search
    a_sorted = sorted(A)
    left = 0
    right = N
    mid = N // 2
    C = N*(N+1) // 2
    while True:
        if search(a_sorted[mid]) <= C // 2:
            if mid == N-1:
                break
            elif search(a_sorted[mid+1]) > C // 2:
                break
            else:
                left = mid
                mid = (mid + right) // 2
        else:
            right = mid + 1
            mid = (mid + left) // 2

    return a_sorted[mid]


if __name__ == "__main__":
    N = int(input())
    A = [int(s) for s in input().split()]
    ans = median_of_medians(N, A)
    print(ans)
### BUGGY CODE ###

N = int(input())
num = 0
list1 = []
for i in range(N):
    list1.append(input())
    flg = 0
    for j in range(i):
        if list1[i]==list1[j]:
            flg = 1
    if flg == 0:
        num += 1
print(num)


### FIXED CODE ###

N = int(input())
list1 = set()
for i in range(N):
    taisho = input()
    if not taisho in list1:
        list1.add(taisho)
print(len(list1))
### BUGGY CODE ###

N, K, C = map(int, input().split())
S = list(input())
list_o = []
for i in range(N):
  if S[i] == "o":
    list_o.append(i)
#oの日だけをピックアップ

bef1 = -2 * 10 ** 5
worklist1 = []
for num1 in list_o:
  if num1 - bef1 > C:
    worklist1.append(num1)
    bef1 = num1
#worklist1の中に、一番単純に思いつく組み合わせを入れる

if len(worklist1) < K:
  exit()
#一個も組み合わせなかったら

else:
  for num2 in worklist1:
    bef2 = -2 * 10 ** 5
    list_o.remove(num2)
    worklist2 = []
    for num3 in list_o:
      if num3 - bef2 > C:
        worklist2.append(num3)
        bef2 = num3
    #ひとつ抜いた状態でworklist2を作ってみる
    list_o.append(num2)
    list_o.sort()
    #list_oを元どおりに
    if len(worklist2) < K:
      print(num2 + 1)
#worklist1の中身をひとつずつ抜いてみて、他に組み合わせが作れないならその項は不可欠だから出力

### FIXED CODE ###

N, K, C = map(int, input().split())
S = list(input())
S_work = []
s = []
f = []
i = 0
while len(s) < K:
  if S[i] == "o":
    s.append(i)
    i += C + 1
  elif S[i] == "x":
    i += 1
  elif i == len(S):
    break
i = 1
while len(f) < K:
  if S[N - i] == "o":
    f.append(N - i)
    i += C + 1
  elif S[N - i] == "x":
    i += 1
  elif i == len(S):
    break
f.sort()
for i in range(K):
  if s[i] == f[i]:
    print(s[i] + 1)
### BUGGY CODE ###

import collections

n = int(input())
s= [input() for _ in range(n)]

ans = []
c = collections.Counter(s)
for k, v in c.most_common():
    if v == c.most_common()[0][1]:
        ans.append(k)
ans = sorted(ans)
for i in ans:
    print(i)

### FIXED CODE ###

import collections

n = int(input())
d = {}
for _ in range(n):
    s = input()
    if d.get(s):
        d[s] += 1
    else:
        d[s] = 1
m = 0
ans = []
for k, v in d.items():
    if m < v:
        m = v
        ans = [k]
    elif m == v:
        ans.append(k)
for i in sorted(ans):
    print(i)
### BUGGY CODE ###

class BinaryIndexTree:  # 1-indexed
    def __init__(self, n):
        self.size = n
        self.tree = [0] * (n + 1)

    def sum(self, i):
        s = 0
        while i > 0:
            s += self.tree[i]
            i -= i & -i
        return s

    def add(self, i, x):
        while i <= self.size:
            self.tree[i] += x
            i += i & -i


if __name__ == "__main__":
    N = int(input())
    S = list(input())
    d = {x: i for i, x in enumerate("abcdefghijklmnopqrstuvwxyz")}
    BIT = [BinaryIndexTree(N) for _ in range(26)]

    # initialize
    for i, s in enumerate(S, start=1):
        BIT[d[s]].add(i, 1)

    Q = int(input())
    ans = []
    for _ in range(Q):
        query, x, y = input().split()
        if query == "1":
            i = int(x)
            c_new = y
            c_old = S[i - 1]
            BIT[d[c_new]].add(i, 1)
            BIT[d[c_old]].add(i, -1)
            S[i - 1] = c_new
        else:
            cnt = 0
            l = int(x) - 1
            r = int(y)
            for b in BIT:
                tmp = b.sum(r) - b.sum(l)
                if tmp:
                    cnt += 1
            ans.append(cnt)

    print(*ans, sep="\n")


### FIXED CODE ###

class BinaryIndexTree:  # 1-indexed
    def __init__(self, n):
        self.size = n
        self.tree = [0] * (n + 1)

    def sum(self, i):
        s = 0
        while i > 0:
            s += self.tree[i]
            i -= i & -i
        return s

    def add(self, i, x):
        while i <= self.size:
            self.tree[i] += x
            i += i & -i


if __name__ == "__main__":
    N = int(input())
    S = list(input())
    d = {x: i for i, x in enumerate("abcdefghijklmnopqrstuvwxyz")}
    BIT = [BinaryIndexTree(N) for _ in range(26)]

    # initialize
    for i, s in enumerate(S, start=1):
        BIT[d[s]].add(i, 1)

    Q = int(input())
    ans = []
    for _ in range(Q):
        query, x, y = input().split()
        if query == "1":
            i = int(x)
            c_new = y
            c_old = S[i - 1]
            BIT[d[c_new]].add(i, 1)
            BIT[d[c_old]].add(i, -1)
            S[i - 1] = c_new
        else:
            cnt = 0
            l = int(x) - 1
            r = int(y)
            for b in BIT:
                tmp = b.sum(r) - b.sum(l)
                if tmp:
                    cnt += 1
            ans.append(cnt)

    print(*ans, sep="\n")
### BUGGY CODE ###

n= int(input())
a= list(map(int, input().split()))
for i in range(n):
    print(a.index(i+1)+1,end=" ")

### FIXED CODE ###

n= int(input())
a= list(map(int, input().split()))
b=[]
for i in range(1,n+1):
    b.append([a[i-1],i])
b.sort()
for i in b:
    print(i[1],end=" ")
### BUGGY CODE ###

A, B, C, X, Y = [int(i) for i in input().split()]

mincost = 10000000000

for a in range(X + 1):
    for b in range(Y + 1):
        c = max([(X - a) * 2, (Y - b) * 2])
        cost = a * A + b * B + c * C
        if (cost < mincost):
            mincost = cost

print(mincost)

### FIXED CODE ###

A, B, C, X, Y = [int(i) for i in input().split()]

cost1 = X * A + Y * B

c = X * 2
a = 0
b = max([0, Y - c / 2])
cost2 = a * A + b * B + c * C

c = Y * 2
a = max([0, X - c / 2])
b = 0
cost3 = a * A + b * B + c * C

print(int(min([cost1, cost2, cost3])))
### BUGGY CODE ###

N = int(input())
import numpy as np
matrix = np.zeros((N,N),dtype="int8")
for n in range(N):
    A = int(input())
    for a in range(A):
        array = [int(i) for i in input().split()]
        matrix[n,array[0]-1] = 1 if array[1] == 1 else -1
l = [True,False]
from itertools import product
for pattern in product(l,repeat=N):
    able = True
    for i,p in enumerate(pattern):
        if p:
            for a,b in zip(matrix[i],pattern):
                if (b==True and a==-1) or (b==False and a == 1):
                    able = False
                    break
            if able == False:
                break
        else:
            pass
    if able == True:
        break
print(sum(pattern))

### FIXED CODE ###

N = int(input())
matrix = [[0 for i in range(N)] for j in range(N)]
for n in range(N):
    A = int(input())
    for a in range(A):
        array = [int(i) for i in input().split()]
        matrix[n][array[0]-1] = 1 if array[1] == 1 else -1
l = [True,False]
from itertools import product
for pattern in product(l,repeat=N):
    able = True
    for i,p in enumerate(pattern):
        if p:
            for a,b in zip(matrix[i],pattern):
                if (b==True and a==-1) or (b==False and a == 1):
                    able = False
                    break
            if able == False:
                break
        else:
            pass
    if able == True:
        break
print(sum(pattern))
### BUGGY CODE ###

import sys

stdin = sys.stdin
sys.setrecursionlimit(10 ** 7)

ri = lambda: int(rs())
rl = lambda: list(map(int, stdin.readline().split()))  # applies to only numbers
rs = lambda: stdin.readline().rstrip()  # ignores trailing space

def F(grid):
    def black(x, y):
        dx = [1, 0, -1, 0]
        dy = [0, 1, 0, -1]
        for k in range(4):
            nx = x + dx[k]
            ny = y + dy[k]
            if 0 <= ny and ny <= H-1 and 0 <= nx and nx <= W-1 and \
                    grid[ny][nx] == '.':
                grid[ny][nx] = '#'
                data[ny][nx] = 'Visited'

    data = [[None] * W for _ in range(H)]
    for i in range(H):
        for j in range(W):
            if grid[i][j] == '#' and data[i][j] == None:
                black(i, j)
    
    return grid

H, W = rl()
A = [list(rs()) for _ in range(H)]
answer = 0
while True:
    if all([x.count('.')==0 for x in A]):
        break
    A = F(A)
    answer += 1

print(answer)
# 54


### FIXED CODE ###

import sys
from collections import deque

stdin = sys.stdin
sys.setrecursionlimit(10 ** 7)

ri = lambda: int(rs())
rl = lambda: list(map(int, stdin.readline().split()))  # applies to only numbers
rs = lambda: stdin.readline().rstrip()  # ignores trailing space

H, W = rl()
A = [list(rs()) for _ in range(H)]
answer = 0
que = deque()
data = [[-1] * W for _ in range(H)]
for i in range(H):
    for j in range(W):
        if A[i][j] == '#':
            data[i][j] = 0
            que.append((j, i))
while que:
    dx = [1, 0, -1, 0]
    dy = [0, 1, 0, -1]
    p = que.popleft()
    for i in range(4):
        nx = p[0] + dx[i]
        ny = p[1] + dy[i]
        if 0 <= ny <= H-1 and 0 <= nx <= W-1:
            if data[ny][nx] == -1:
                data[ny][nx] = data[p[1]][p[0]] + 1
                que.append((nx, ny))
answer = max([max(z) for z in data])
print(answer)
# 54
### BUGGY CODE ###

n = int(input())
initial_vals = list(map(int, input().split(" ")))


table = [[None for x in range(n)] for x in range(n)]

for i in range(n - 1):
    table[i][i + 1] = abs(initial_vals[i] - initial_vals[i + 1])
    if len(initial_vals) > i + 2:
        table[i][i + 2] = abs(initial_vals[i] - initial_vals[i + 2])


def calc(from_stone, to_stone):
    if table[from_stone][to_stone] is not None:
        return table[from_stone][to_stone]
    elif (to_stone - from_stone) == 2:
        table[from_stone][to_stone] = min(
            table[from_stone][to_stone],
            table[from_stone][to_stone - 1] + table[to_stone - 1][to_stone],
        )
        return table[from_stone][to_stone]
    else:
        table[from_stone][to_stone] = min(
            calc(from_stone, to_stone - 1) + table[to_stone - 1][to_stone],
            calc(from_stone, to_stone - 2) + table[to_stone - 2][to_stone],
        )
        return table[from_stone][to_stone]


print(calc(0, n - 1))


### FIXED CODE ###

n = int(input())
initial_vals = list(map(int, input().split(" ")))


# print(calc(0, n - 1))


arr = [0 for x in range(n)]

arr[1] = abs(initial_vals[0] - initial_vals[1])

for i in range(2, len(arr)):
    arr[i] = min(
        arr[i - 1] + abs(initial_vals[i - 1] - initial_vals[i]),
        arr[i - 2] + abs(initial_vals[i - 2] - initial_vals[i]),
    )

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

from collections import Counter
class Combination:
    _maxNum = 0
    _divider = 0
    _fact = []
    _inv = []
    _finv = []

    def __init__(self, maxNum, divider):
        self._maxNum = maxNum
        self._divider = divider
        self._fact = [0] * (self._maxNum + 1)
        self._fact[0] = self._fact[1] = 1

        if self._divider != 0:
            self._inv = [0] * (self._maxNum + 1)
            self._finv = [0] * (self._maxNum + 1)
            self._inv[0] = self._inv[1] = self._finv[0] = self._finv[1] = 1

        for i in range(2, self._maxNum + 1):
            self._fact[i] = self._fact[i - 1] * i;
            if self._divider != 0:
                self._fact[i] %= self._divider
                self._inv[i] = self._divider - self._inv[self._divider % i] * (self._divider // i) % self._divider
                self._finv[i] = self._finv[i - 1] * self._inv[i] % self._divider

    def nPk(self, n, k):
        if(k > self._maxNum) or (n > self._maxNum) or (k > n) or (k < 0) or (n < 0):
            return 0
        return(self._fact[n] // self._fact[n - k])

    def nCk(self, n, k):
        ans = 0
        if(k > self._maxNum) or (n > self._maxNum) or (k > n) or (k < 0) or (n < 0):
            ans = 0
        elif self._divider == 0:
            ans = self.nPk(n, k)
            ans //= self._fact[k]
        else:
            ans = self._fact[n] * (self._finv[k] * self._finv[n - k] % self._divider) % self._divider

        return ans

def ABC137C_GreenBin():
    N = int(input().strip())

    di = Counter()
    for i in range(N):
        s = ''.join(sorted(input().strip()))
        di[s] += 1
    
    cmb = Combination(N, 0)

    ans = 0
    for num in di.values():
        ans += cmb.nCk(num, 2)

    print(ans)


def main():
    ABC137C_GreenBin()

if __name__ == "__main__":
    main()


### FIXED CODE ###

from collections import Counter

def ABC137C_GreenBin():
    N = int(input().strip())
    S = [input().strip() for i in range(N)]

    ans = 0
    di = Counter()
    for s in S:
        s = ''.join(sorted(list(s)))
        
        if s in di:
            ans += di[s]

        di[s] += 1
    
    print(ans)


def main():
    ABC137C_GreenBin()

if __name__ == "__main__":
    main()