Problem:
Score : 300 points

Problem Statement

We will call a string obtained by arranging the characters contained in a string a in some order, an anagram of a.

For example, greenbin is an anagram of beginner. As seen here, when the same character occurs multiple times, that character must be used that number of times.

Given are N strings s_1, s_2, \ldots, s_N. Each of these strings has a length of 10 and consists of lowercase English characters. Additionally, all of these strings are distinct. Find the number of pairs of integers i, j (1 \leq i < j \leq N) such that s_i is an anagram of s_j.

Constraints

2 \leq N \leq 10^5

s_i is a string of length 10.

Each character in s_i is a lowercase English letter.

s_1, s_2, \ldots, s_N are all distinct.

Input

Input is given from Standard Input in the following format:

N
s_1
s_2
:
s_N

Output

Print the number of pairs of integers i, j (1 \leq i < j \leq N) such that s_i is an anagram of s_j.

Sample Input 1

3
acornistnt
peanutbomb
constraint

Sample Output 1

1

s_1 = acornistnt is an anagram of s_3 = constraint. There are no other pairs i, j such that s_i is an anagram of s_j, so the answer is 1.

Sample Input 2

2
oneplustwo
ninemodsix

Sample Output 2

0

If there is no pair i, j such that s_i is an anagram of s_j, print 0.

Sample Input 3

5
abaaaaaaaa
oneplustwo
aaaaaaaaba
twoplusone
aaaabaaaaa

Sample Output 3

4

Note that the answer may not fit into a 32-bit integer type, though we cannot put such a case here.

Solution in C (GCC 5.4.1) (judge verdict: Accepted)

#include <float.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

// 内部定数
#define D_STR_MAX		200005									// 最大文字列数
#define D_STR_LEN		10										// 文字列長

// 内部変数
static FILE *szpFpI;											// 入力
static char sc2Str[D_STR_MAX][D_STR_LEN + 5];					// 文字列
static char *scp1Str[D_STR_MAX];								// 文字列
static int siSCnt;												// 文字列数

// 内部変数 - テスト用
#ifdef D_TEST
	static int siRes;
	static FILE *szpFpA;
	static int siTNo;
#endif

// 出力
int
fOut(
	char *pcpLine				// <I> １行
)
{
	char lc1Buf[1024];

#ifdef D_TEST
	fgets(lc1Buf, sizeof(lc1Buf), szpFpA);
	if (strcmp(lc1Buf, pcpLine)) {
		siRes = -1;
	}
#else
	printf("%s", pcpLine);
#endif

	return 0;
}

// ソート関数 - char昇順
int
fSortFncCU(
	const void *pzpVal1			// <I> 値１
	, const void *pzpVal2		// <I> 値２
)
{
	char *lcpVal1 = (char *)pzpVal1;
	char *lcpVal2 = (char *)pzpVal2;

	// char昇順
	if (*lcpVal1 > *lcpVal2) {
		return 1;
	}
	else if (*lcpVal1 < *lcpVal2) {
		return -1;
	}

	return 0;
}

// ソート関数 - 文字列昇順
int
fSortFncSU(
	const void *pzpVal1			// <I> 値１
	, const void *pzpVal2		// <I> 値２
)
{
	char **lcppVal1 = (char **)pzpVal1;
	char **lcppVal2 = (char **)pzpVal2;

	// 文字列昇順
	return strncmp(*lcppVal1, *lcppVal2, D_STR_LEN);
}

// 実行メイン
long long
fMain(
)
{
	int i, liRet;
	char lc1Buf[1024];

	// 文字列数 - 取得
	fgets(lc1Buf, sizeof(lc1Buf), szpFpI);
	sscanf(lc1Buf, "%d", &siSCnt);

	// 文字列 - 取得
	for (i = 0; i < siSCnt; i++) {
		fgets(sc2Str[i], sizeof(sc2Str[i]), szpFpI);
		qsort(sc2Str[i], D_STR_LEN, sizeof(char), fSortFncCU);
		scp1Str[i] = sc2Str[i];
	}
	sc2Str[siSCnt][0] = 0;
	scp1Str[siSCnt] = sc2Str[siSCnt];

	// 文字列 - ソート
	qsort(scp1Str, siSCnt, sizeof(char *), fSortFncSU);

	// 個数 - 取得
	long long llCnt = 0;
	long long llSame = 1;
	for (i = 0; i < siSCnt; i++) {
		
		// 次と比較
		liRet = fSortFncSU(&scp1Str[i], &scp1Str[i + 1]);
		if (liRet == 0) {
			llSame++;
		}
		else {
			llCnt += llSame * (llSame - 1) / 2;
			llSame = 1;
		}
	}

	return llCnt;
}

// １回実行
int
fOne(
)
{
	long long llRet;
	char lc1Buf[1024];

	// 入力 - セット
#ifdef D_TEST
	sprintf(lc1Buf, ".\\Test\\T%d.txt", siTNo);
	szpFpI = fopen(lc1Buf, "r");
	sprintf(lc1Buf, ".\\Test\\A%d.txt", siTNo);
	szpFpA = fopen(lc1Buf, "r");
	siRes = 0;
#else
	szpFpI = stdin;
#endif

	// 実行メイン
	llRet = fMain();

	// 出力
	sprintf(lc1Buf, "%lld\n", llRet);
	fOut(lc1Buf);

	// 残データ有無
#ifdef D_TEST
	lc1Buf[0] = '\0';
	fgets(lc1Buf, sizeof(lc1Buf), szpFpA);
	if (strcmp(lc1Buf, "")) {
		siRes = -1;
	}
#endif

	// テストファイルクローズ
#ifdef D_TEST
	fclose(szpFpI);
	fclose(szpFpA);
#endif

	// テスト結果
#ifdef D_TEST
	if (siRes == 0) {
		printf("OK %d\n", siTNo);
	}
	else {
		printf("NG %d\n", siTNo);
	}
#endif

	return 0;
}

// プログラム開始
int
main()
{

#ifdef D_TEST
	int i;
	for (i = D_TEST_SNO; i <= D_TEST_ENO; i++) {
		siTNo = i;
		fOne();
	}
#else
	fOne();
#endif

	return 0;
}