立方词(cubeword)是一种特殊的填字游戏。在构建立方词时,首先选择一个正整数 $a$:立方体的边长。然后,构建一个由 $a \times a \times a$ 个单位立方体组成的大立方体。这个大立方体有 12 条棱。接着,舍弃所有不接触大立方体棱的单位立方体。下图展示了 $a = 6$ 时得到的物体。
最后,为物体中的每个单位立方体分配一个字母。大立方体的每条棱上必须构成一个有意义的单词。每条棱都可以双向读取,只要其中一个方向能读出有意义的单词即可。
下图展示了 $a = 6$ 时,部分单位立方体已被分配字母的物体。你已经可以在大立方体的三条棱上读出单词“SUBMIT”、“ACCEPT”和“TURING”。
给定一个有效单词列表。列表中的每个单词可以出现在有效立方词的任意多条棱上。请计算并输出可以构建出的不同立方词的数量,结果对 $998,244,353$ 取模。
如果一个立方词可以通过旋转或镜像得到另一个立方词,它们仍被视为不同的立方词。
输入格式
第一行包含一个整数 $n$ ($1 \le n \le 100,000$),表示单词的数量。
接下来 $n$ 行,每行包含一个可以出现在大立方体棱上的单词。每个单词的长度在 3 到 10 之间(含 3 和 10)。
保证所有单词各不相同。
输出格式
输出一个整数,表示给定有效单词列表下,不同立方词的数量,结果对 $998,244,353$ 取模。
子任务
子任务 1(21 分):单词仅由字母 ‘a’ - ‘f’(小写)组成。 子任务 2(29 分):单词仅由字母 ‘a’ - ‘p’(小写)组成。 子任务 3(34 分):单词由字母 ‘a’ - ‘p’(小写)和 ‘A’ - ‘P’(大写)组成。 子任务 4(16 分):单词由字母 ‘a’ - ‘z’(小写)、‘A’ - ‘Z’(大写)和数字 ‘0’ - ‘9’ 组成。
样例
样例输入 1
1 radar
样例输出 1
1
样例输入 2
1 robot
样例输出 2
2
样例输入 3
2 FLOW WOLF
样例输出 3
2
样例输入 4
2 baobab bob
样例输出 4
4097
样例输入 5
3 TURING SUBMIT ACCEPT
样例输出 5
162
样例输入 6
3 MAN1LA MAN6OS AN4NAS
样例输出 6
114
说明
在第一个样例中,唯一的可能性是每条棱上都是单词“radar”。
在第二个样例中,有两个立方体,它们互为旋转关系——单词“robot”出现在每条棱上,两个立方体的区别在于左下前角包含的是 ‘r’ 还是 ‘t’。
第三个样例与第二个类似。每条棱上的单词可以双向读取这一事实不影响答案。
在第四个样例中,有一个每条棱上都是单词“bob”的立方体。此外,还有 $2^{12} = 4096$ 个每条棱上都是单词“baobab”的立方体。(对于 12 条棱中的每一条,单词“baobab”都有两种可能的读取方向。)