1 条题解
-
0
核心结论(一句话)
- 能无限减 → 输出 -1
- 最多只能减 1 → 输出总和 -1
- 完全不能减 → 输出原总和
代码只做三件事:
- 检查原数组是否稳定(
good()) - 把最小值减 1,再检查是否稳定
- 都不稳定 → 无限减(-1)
1. 题目核心机制(关键观察)
每次操作选 k 个元素,能真正减少总和的充要条件:
$$\exists\ i < n,\ \exists\ a_j, a_k \text{ 满足 } \ \ a_j \not\equiv a_k \pmod i $$或者: 数组总和不能被 n 整除。
2. 最终稳定态定义(good 函数)
数组再也无法减少的充要条件:
$$\forall\ 2 \le i \le n-1,\quad \forall\ j:\ \ a_j \equiv a_0 \pmod i $$并且:
重要推论
- 当 n > 23 时,满足所有同余条件 → 所有数必须完全相等
- 当 n ≤ 23 时,只需检查模
2~n-1全部同余
3. 完整判定逻辑(官方解法)
1. 若原数组已经是稳定态 → 答案 = 总和 2. 否则,把最小值减 1,再检查 若此时稳定 → 答案 = 总和 - 1 3. 否则 → 可以无限减 → 输出 -1
4. 标程代码逐行详解
(1)good() 函数:判断数组是否稳定
bool good() { bool ok = 1; if (n > 23) { // n>23 时,必须全部相等才能稳定 for (int i=0;i<n;i++) { if (a[i] != a[0]) ok = 0; } } else { // n<=23 时,检查所有 2<=i<=n-1 同余 for (int i=2;i<n;i++) { for (int j=0;j<n;j++) { if (a[j]%i != a[0]%i) { ok = 0; break; } } } } // 总和必须被 n 整除 ok &= (s % n == 0); return ok; }(2)主逻辑
sort(a.begin(), a.end()); if (good()) { cout << s << "\n"; continue; } // 尝试把最小值减 1 a[0]--; s--; if (good()) { cout << s << "\n"; continue; } // 都不行 → 无限减 cout << -1 << "\n";
5. 为什么 n > 23 直接判全相等?
因为:
而题目中 。 → 满足所有同余条件 等价于所有数相等。
6. 样例解释
样例 1
2 2 1- 原数组不稳定
- 减 1 →
[1,1]稳定 - 输出:2
样例 2
4 3 3 3 3- 全相等,总和被 4 整除
- 输出:12
样例 3
8 1 2 ... 8- 原数组不稳定
- 减 1 后仍不稳定
- 输出:-1
7. 时间复杂度
完美通过 。
8. 最简记忆口诀(背这个就够)
- n>23:必须全相等才不能减
- n≤23:所有数模 2~n-1 都同余
- 总和必须被 n 整除
- 能减就减 最多 1
- 否则 -1
- 1
信息
- ID
- 6709
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者