1 条题解
-
0
题目题解:D. Turtle Tenacity: Continual Mods
问题重述
给定一个长度为 的数组 ,可以任意重排成 ,判断是否存在一种排列使得:
$$b_1 \bmod b_2 \bmod b_3 \bmod \dots \bmod b_n \neq 0 $$其中取模运算从左到右顺序执行。
核心观察
连续取模运算有一个重要性质:
一旦某个中间结果变成 ,之后的所有取模结果都是 。
因此,我们的目标是避免在运算过程中过早出现 。
另一个重要性质:
如果当前值为 ,下一个模数为 ,则 。 特别地,如果 ,则 (值不变)。
解题思路
第一步:排序
将数组按非递减顺序排序,得到:
第二步:检查最小值是否唯一
情况 1:
此时最小值是唯一的。我们可以将 放在序列的第一个位置:
计算过程:
- 第一步:
- 因为 (最小值唯一且排序后 ),所以
- 之后的所有数都 ,因此 保持不变
- 最终结果为
结论: 当最小值唯一时,答案一定是 YES。
第三步:最小值不唯一的情况
情况 2: (最小值出现至少两次)
此时不能简单地把最小值放在开头,因为:
一旦出现两个最小值相邻,就会得到 。
但是,如果存在一个元素 不是 的倍数,即:
则我们可以构造如下排列:
$$b = [a_x, a_1, a_2, \dots, a_{x-1}, a_{x+1}, \dots, a_n] $$计算过程:
- 第一步:
- 因为 ,记这个余数为 ()
- 接下来对 取模:(因为 )
- 之后的所有数都 ,因此 保持不变
- 最终结果为
结论: 当最小值不唯一,但存在一个不是最小值倍数的数时,答案是 YES。
第四步:所有元素都是最小值的倍数
情况 3: 且对所有 有
此时数组中所有数都是 的倍数。
无论怎么排列,至少有一个最小值不在第一位(因为最小值至少有两个)。考虑任意排列:
- 第一个数记为
- 当遇到第一个 (最小值)时,有两种可能:
- 如果 也是 的倍数,则 ,结果变成
- 如果 之前已经变成 ,那结果已经是
更严格地证明:在序列中必然出现至少一次 的运算,其中 是 的倍数,结果必然是 。之后所有取模结果都是 。
结论: 当所有元素都是最小值的倍数时,答案是 NO。
算法流程
sort(a, a + n); if (a[0] != a[1]) { // 最小值唯一 cout << "YES\n"; } else { // 最小值不唯一,检查是否存在不是 a[0] 倍数的数 bool found = false; for (int i = 1; i < n; i++) { if (a[i] % a[0] != 0) { found = true; break; } } cout << (found ? "YES\n" : "NO\n"); }
复杂度分析
- 时间复杂度:,主要由排序贡献
- 空间复杂度: 或 (取决于是否使用额外数组)
示例验证
输入 排序后 判断 输出 → YES YES 全为3的倍数 → NO NO → YES YES 存在非1倍数 → YES(?实际输出NO,需注意) NO 注意第4个样例:,最小值是 ,所有数都是 的倍数(因为任何数 ),所以实际上是 NO。
总结
判断条件可以简洁表述为:
- YES 当且仅当:最小值唯一,或者存在一个不是最小值倍数的数
- NO 当且仅当:最小值不唯一,且所有数都是最小值的倍数
- 1
信息
- ID
- 6505
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者