1 条题解
-
0
G. 樱子的任务 - 详细题解
问题重述
给定一个长度为 的数组 ,允许进行操作:选择 且 ,将 替换为 或 。求经过任意次操作后, 的最大可能值。
其中 表示数组中缺失的第 个非负整数。
关键观察
观察 1: 的情况
当 时,无法进行任何操作(因为需要两个不同的下标),数组无法改变。
因此, 就是原数组的 。
观察 2: 时的数论性质
设 。
根据数论知识,通过反复执行 的操作(类似于辗转相除法),我们可以生成所有 的倍数,并且只能生成 的倍数。
重要结论:
- 我们可以将任意元素变为
- 我们可以生成任意 的倍数(包括负数和正数)
- 由于操作要求 ,我们实际上只能生成非负数
最优策略:将数组变为最小的 个 的倍数,即:
这样可以让最小的非负整数尽可能密集地覆盖,从而最大化 。
观察 3:为什么是最优的?
- 数组中的数只能是 的倍数
- 要最大化第 个缺失的数,我们希望数组尽可能密集地覆盖从小到大的数
- 最优方案就是取最小的 个非负 的倍数:
问题转化
设最优数组为:
我们需要找到这个数组的 。
计算
方法
设 为当前已经考虑的最后一个数,初始 。
遍历数组 (包括一个虚拟的无穷大结尾),对于每个 :
- 区间 中的整数都是缺失的
- 区间长度为
- 如果 区间长度,则答案在区间内,输出
- 否则, 减去区间长度, 更新为 ,继续
算法步骤
- 读入 和数组
- 如果 :
- 直接输出 (因为只有一个数,第 个缺失的就是 ?需要验证)
- 实际上当 时,数组只有一个数 ,缺失的数依次为 (跳过 )
- 如果 ,则 ;否则
- 标程中用 的情况处理,输出
- 计算
- 构造最优数组
- 遍历 ,计算
完整代码
#include <bits/stdc++.h> using namespace std; int main() { ios_base::sync_with_stdio(false); cin.tie(0); int t; cin >> t; while (t--) { int n, k; cin >> n >> k; vector<long long> a(n); long long g = 0, mx = 0; for (int i = 0; i < n; i++) { cin >> a[i]; g = __gcd(g, a[i]); mx = max(mx, a[i]); } // n = 1 的情况 if (g == 0) { cout << k << "\n"; continue; } // 构造最优数组: 0, g, 2g, ..., (n-1)g sort(a.begin(), a.end()); long long q = -g; for (int i = 0; i < n; i++) { q += g; a[i] = q; } // 添加虚拟结尾 a.push_back(1e16); long long lst = -1; for (int i = 0; i <= n; i++) { if (k <= a[i] - lst - 1) { break; } k -= max(a[i] - lst - 1, 0LL); lst = a[i]; } cout << lst + k << "\n"; } return 0; }
算法图解
以样例
n=4, k=5, a=[2,2,2,16]为例:- 计算
- 最优数组:
- 计算 :
区间 缺失数 累计缺失 k=5 (-1, 0) 长度 0 0 k=5 (0, 2) 缺失 {1} 1 k=4 (2, 4) 缺失 {3} 2 k=3 (4, 6) 缺失 {5} 3 k=2 (6, ∞) 缺失 {7,8,9,...} - 当遍历到区间 时, 区间长度 ,继续:
然后进入区间 ,此时 无穷大,答案
输出: ✓
时间复杂度
- 计算 gcd:
- 排序:
- 遍历:
- 总复杂度: 每个测试用例
示例验证
最优数组 输出 1 3 [3] 0 - 3 2 10 [1,1] 1 [0,1] 第10个缺失:11 11 3 1 [1,2,3] [0,1,2] 第1个缺失:3 3 2 [1,2,4] 第2个缺失:4 4 4 5 [2,2,2,16] 2 [0,2,4,6] 第5个缺失:8 8 [2,2,2,3] 1 [0,1,2,3] 与样例输出完全一致。
关键公式总结
$$\boxed{\text{最优数组} = [0, g, 2g, 3g, \dots, (n-1)g]} $$$$\boxed{\operatorname{mex}_k = \text{第 } k \text{ 个不在该数组中的非负整数}} $$其中 。
- 1
信息
- ID
- 6331
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 3
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者