1 条题解
-
0
题意
定义一个操作 :取所有 的和 ,排序后保留最小的 个数,作为新数组。
重复应用 共 次,最终得到一个单元素数组。求这个元素的值,对 取模。
关键观察
设当前数组为 (已排序)。
考虑所有两两和 ()。
最小的和显然是 。
第二小的可能是 或 (若允许 则 ,但这里 不允许相同下标,所以 不合法)。
实际上,最小的 个和具有特殊结构。
核心结论
经过分析,每次变换后的数组元素可以表示为:
- 新数组的第一个元素是
- 其余元素是 ()的一些组合
更具体地,变换后的数组等价于:
$$[\,a_1+a_2,\; a_1+a_3,\; a_1+a_4,\; \dots,\; a_1+a_n\,] $$但需要排序,且长度变为 。实际上,这个序列已经单调不减(因为 ),所以就是这 个数。
变换规律
设当前数组为 。
$$[\,b_1+b_2,\; b_1+b_3,\; b_1+b_4,\; \dots,\; b_1+b_m\,] $$
则下一次变换后的数组为:即每个元素减去 后,新数组为 每个加上 。
因此,我们可以用增量累加的方式模拟:
- 每次取出当前最小值
- 将答案 更新为 (因为每次变换后,最终结果都会受到 的影响,且后续会累加)
- 然后从数组中移除 ,并将剩余所有元素减去 (这相当于后续的 变成 )
算法步骤
. 对数组排序。 . 初始化答案 。 . 当 时:
- 取出最小值
- 将 每个元素减去
- 删除 (即把 左移一位)
- 减 1 . 输出 (注意最后不需要再加 ,因为最后一步已经包含在累加中)
正确性说明
每次变换相当于:新数组 = ,其中 是原最小值。
最终结果可以通过递推得到:因此用递推累加即可。
示例验证
样例 1
输入:
5 1 2 4 5 6排序后:
- 第1步:, , 数组变为
- 第2步:, , 数组变为
- 第3步:, , 数组变为
- 第4步:, , 数组变为 输出 ✅
样例 4
输入:
3 1000000000 1000000000 777排序后:
- 第1步:, , 数组变为
- 第2步:, 模
计算:,乘 2 得 ,模 得 ✅
完整代码
#include <bits/stdc++.h> using namespace std; const int MOD = 1e9 + 7; int main() { int n; cin >> n; vector<long long> a(n); for (int i = 0; i < n; i++) cin >> a[i]; sort(a.begin(), a.end()); long long ans = 0; while (n > 1) { long long x = a[0]; ans = (ans + x) * 2 % MOD; for (int i = 1; i < n; i++) a[i] -= x; for (int i = 1; i < n; i++) a[i-1] = a[i]; n--; } cout << ans << "\n"; return 0; }
复杂度
- 每次循环 平移数组,总复杂度 , 可过。
- 空间 。
- 1
信息
- ID
- 6677
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 2
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者