Snowfall 的题解
记住只在没有思路时使用题解,不要从它复制粘贴代码。请尊重题目和题解的作者。
在解题之前提交题解的代码会导致封禁。
在解题之前提交题解的代码会导致封禁。
作者:
概述
本题要求重新排列数组,使乘积能被 整除的子数组数量最小。
核心解法是将所有被 整除的数放在一端,再将偶数(但不被
整除)与
的倍数(但不被
整除)分开,中间放置其他数,从而最小化同时包含
因子和
因子的子数组数量。
分析
核心观察
乘积能被 整除当且仅当子数组中至少有一个偶数(含因子
)且至少有一个
的倍数(含因子
)。
被 整除的数同时提供两种因子,包含它的任意子数组都满足条件,因此应集中放在一端以减少其参与的子数组数量。
思路
将每个数按因子分类:
:被
整除(提供因子
和
);
:能被
整除但不能被
整除(仅提供因子
);
:能被
整除但不能被
整除(仅提供因子
);
:既不能被
整除也不能被
整除(不提供任何因子)。
设数量分别为 。
所有包含 的子数组一定满足条件。若将全部
连续放在数组的一端,则包含
的子数组数量最小,为:
其中 为总长度。
不包含 的剩余部分长度为
,只由
组成。这部分中,满足条件的子数组必须同时包含至少一个
和一个
。对于任意
位置和
位置,它们之间(无论中间有什么)构成的子数组都满足条件,因此这类子数组数量至少为
。通过将全部
放在一侧、全部
放在另一侧,中间放置所有
,恰好达到这个下界。所以总最小数量为:
具体示例
以样例 的数组
为例。分类得
(
),
(
),
(
),
(
)。采用排列
,包含
的子数组数量为总子数组数
减去不包含
的右侧部分
的子数组数
,即
;跨
的子数组数为
;总数为
,与样例一致。
算法步骤
- 读入测试用例数
。
- 对每个测试用例,读入
和数组
a。 - 创建四个列表:
c_list,a_list,d_list,b_list。 - 遍历每个数
val:- 若
val % 6 == 0,加入c_list; - 否则若
val % 2 == 0,加入a_list; - 否则若
val % 3 == 0,加入b_list; - 否则加入
d_list。
- 若
- 按顺序连接:
c_list + a_list + d_list + b_list,并输出。
复杂度分析
- 时间复杂度:
,每个测试用例遍历一次数组。
- 空间复杂度:
,存储分类后的元素。
实现注意事项
- 分类条件按先后顺序:先判断是否能被
整除,否则再判断能被
整除等。
- 输出时元素间用空格分隔,行尾无多余空格。
- 使用快速 I/O 处理大量数据。
源代码
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
vector<int> c, a, d, b;
for (int i = 0; i < n; ++i) {
int x;
cin >> x;
if (x % 6 == 0) c.push_back(x);
else if (x % 2 == 0) a.push_back(x);
else if (x % 3 == 0) b.push_back(x);
else d.push_back(x);
}
vector<int> ans;
ans.insert(ans.end(), c.begin(), c.end());
ans.insert(ans.end(), a.begin(), a.end());
ans.insert(ans.end(), d.begin(), d.end());
ans.insert(ans.end(), b.begin(), b.end());
for (size_t i = 0; i < ans.size(); ++i) {
if (i) cout << ' ';
cout << ans[i];
}
cout << '\n';
}
return 0;
}
import sys
def main():
data = sys.stdin.buffer.read().split()
t = int(data[0])
idx = 1
out_lines = []
for _ in range(t):
n = int(data[idx]); idx += 1
c, a, d, b = [], [], [], []
for _ in range(n):
x = int(data[idx]); idx += 1
if x % 6 == 0:
c.append(x)
elif x % 2 == 0:
a.append(x)
elif x % 3 == 0:
b.append(x)
else:
d.append(x)
ans = c + a + d + b
out_lines.append(' '.join(map(str, ans)))
sys.stdout.write('\n'.join(out_lines))
if __name__ == "__main__":
main()
评论