📌  相关文章
📜  国际空间研究组织 | ISRO CS 2011 |问题 75(1)

📅  最后修改于: 2023-12-03 15:23:03.033000             🧑  作者: Mango

国际空间研究组织 | ISRO CS 2011 |问题 75

本题是国际空间研究组织(ISRO)2011年计算机科学考试(ISRO CS 2011)的第75题。

题目描述

有一个长度为 $n$ 的整数序列 $a_1, a_2, ..., a_n$,每个数的范围为 $1$ 到 $n$。现在我们定义“好的三元组”为 $(i, j, k)$,其中 $1 \leq i < j < k \leq n$,且满足 $a_i + a_j + a_k$ 是 $3$ 的倍数。现在,请你写一个程序,统计一共有多少个好的三元组。

输入格式

第一行包含一个整数 $n$。

第二行包含 $n$ 个整数,表示序列 $a_1, a_2, ..., a_n$。

输出格式

输出一个整数,表示好的三元组的个数。

输入样例
5
1 2 3 4 5
输出样例
C\uo!()\i)*TB
解题思路

问题实际上就是求余数为 $0$、$1$、$2$ 的数的个数。假设 $r_0$、$r_1$、$r_2$ 分别表示余数为 $0$、$1$、$2$ 的数的个数,那么好的三元组数量就是 $C(r_0,3)+C(r_1,3)+C(r_2,3)+r_0r_1r_2$。

为什么可以这样计算呢?因为当 $a_i+a_j+a_k$ 为 $3$ 的倍数时,$a_i$、$a_j$、$a_k$ 对 $3$ 取余的和也是 $0$。因此,$a_i$、$a_j$、$a_k$ 中余数相同的个数可以构成好的三元组。

那么如何计算 $r_0$、$r_1$、$r_2$ 呢?可以遍历整个序列,统计余数为 $0$、$1$、$2$ 的数的个数即可。

参考实现
n = int(input())
a = list(map(int, input().split()))

rem = [0] * 3
for x in a:
    rem[x % 3] += 1

ans = rem[0] * (rem[0] - 1) * (rem[0] - 2) // 6 \
    + rem[1] * (rem[1] - 1) * (rem[1] - 2) // 6 \
    + rem[2] * (rem[2] - 1) * (rem[2] - 2) // 6 \
    + rem[0] * rem[1] * rem[2]

print(ans)

代码中,rem[i] 表示余数为 $i$ 的数的个数。ans 表示好的三元组数量。计算过程中使用组合数公式 $C(n,3)=n(n-1)(n-2)/6$。