1 条题解
-
0
Guest
-
0
完整解析
二、阅读程序
(1)
该程序实现了一种类似埃拉托斯特尼筛法(Sieve of Eratosthenes)的算法,用于预处理计算每个数的最小质因数。
-
程序逻辑:
- 初始化一个长度为
n+1的数组p,所有元素为 0。 - 从
i = 2到n遍历。 - 如果
p[i]仍为 0,说明i是一个质数(因为它没有被小于它的数筛掉),因此i的最小质因数是它自己。 - 然后,遍历
i的所有倍数j(从i开始,步长为i)。 - 如果
p[j]仍为 0,说明j还没有被标记过最小质因数,此时遇到的i就是j的最小质因数,因此将p[j]设为i。 - 最后,程序累加从
p[2]到p[n]的所有值并输出。
- 初始化一个长度为
-
题目解析:
- 判断题 (真):根据算法逻辑,
p[i]在循环结束后确实存储了i的最小质因数。例如,p[6]会被 2 筛到,所以p[6]=2;p[7]不会被筛到,所以在i=7的循环中p[7]被置为 7。 - 判断题 (真):当
n=10时,手动模拟:i=2:p[2]=2, p[4]=2, p[6]=2, p[8]=2, p[10]=2。i=3:p[3]=3, p[9]=3。p[6]已被标记,跳过。i=5:p[5]=5。p[10]已被标记,跳过。i=7:p[7]=7。- 其余
p值为 0。所以p数组为{0, 0, 2, 3, 2, 5, 2, 7, 2, 3, 2}(注意 p 和 p 未使用,默认为0)。
- 判断题 (假):这个算法是线性筛的变体,其内层循环
for (int j = i; ...)只对p[j]为 0 的情况执行核心操作。其总执行次数近似于调和级数n/2 + n/3 + n/5 + ...,时间复杂度为 O(n log log n)。O(n log n) 是一个更宽松的上界,但不是最紧确的描述。 - 选择题 (B):当
n=12时,p数组的值为:p[2]=2, p[3]=3, p[4]=2, p[5]=5, p[6]=2, p[7]=7, p[8]=2, p[9]=3, p[10]=2, p[11]=11, p[12]=2。 求和:2+3+2+5+2+7+2+3+2+11+2 = 32。 - 选择题 (B):移除
if (p[j] == 0)后,p[j]的值会被更大的因子覆盖。例如,p[6]先被i=2设为 2,然后被i=3设为 3。p[j]将存储j的最大质因数。对于n=10,新的p值为:p[2]=2, p[3]=3, p[4]=2, p[5]=5, p[6]=3, p[7]=7, p[8]=2, p[9]=3, p[10]=5。 原和为2+3+2+5+2+7+2+3+2=28。 新和为2+3+2+5+3+7+2+3+5=32。输出会变大。
- 判断题 (真):根据算法逻辑,
(2)
该程序使用深度优先搜索(DFS)算法来寻找一个二维字符网格中,由字符
'1'构成的最大连通区域的面积。-
程序逻辑:
dfs(x, y)函数用于从点(x, y)开始,探索所有与之四向连通(上下左右)的'1',并返回这个连通区域的大小。- 函数通过递归调用实现。
visited数组用来防止重复访问同一个点,避免死循环。 main函数遍历整个grid。每当遇到一个未被访问过的'1',就调用dfs计算其所在的连通区域大小,并用max_area记录遇到的最大值。
-
题目解析: 6. 判断题 (假):程序通过递归函数
dfs实现搜索,这是深度优先搜索(DFS)的典型特征。广度优先搜索(BFS)通常使用队列实现。 7. 判断题 (真):如果所有'1'都是连通的,那么dfs函数只会被成功调用一次。main函数的循环会遍历n*m个格子,dfs函数内部也会访问每个'1'格子一次。因此,总时间复杂度与格子总数n*m成正比。 8. 判断题 (真):增加的dx,dy坐标偏移量(1,1), (1,-1), (-1,1), (-1,-1)分别代表右下、右上、左下、左上四个对角线方向。将循环次数改为 8,即可实现八个方向的连通性检查。 9. 选择题 (C):程序遍历所有点,对每个'1'连通块调用dfs计算其大小,并用max_area持续更新最大值。因此,程序旨在寻找最大连通区域的面积。 10. 选择题 (C):输入中有三个连通块: * 左上角 2x2 的区域,面积为 4。 * 中间(2,2)的位置,面积为 1。 * 右下角(3,3), (3,4)的位置,面积为 2。 程序会分别计算出 4、1、2,并取最大值 4 作为输出。
(3)
该程序实现了一个经典的贪心算法,用于解决活动选择问题。
-
程序逻辑:
- 输入
n个活动,每个活动有开始时间和结束时间。注意,代码中cin >> activities[i].second >> activities[i].first表示先读入开始时间存入second,再读入结束时间存入first。 sort函数对pair类型的vector进行排序时,默认先按first成员(即结束时间)升序排序。如果结束时间相同,再按second成员(开始时间)排序。- 贪心策略:首先选择结束时间最早的活动。然后,从剩下的活动中,选择与已选活动不冲突(即开始时间晚于或等于上一个已选活动的结束时间)且结束时间最早的活动。
current_end_time记录上一个被选中的活动的结束时间。遍历排序后的活动列表,只要当前活动的开始时间不早于current_end_time,就选中这个活动,并更新count和current_end_time。
- 输入
-
题目解析: 11. 判断题 (假):根据第 12 行
cin >> activities[i].second >> activities[i].first,程序先将读入的第一个数存入pair的second成员,第二个数存入first成员。结合上下文,程序是按结束时间排序的,所以first对应结束时间,second对应开始时间。因此,输入是先开始时间,后结束时间。 12. 判断题 (假):该算法是贪心算法。它在每一步都做出局部最优选择(选择结束时间最早的活动),并最终达到全局最优。 13. 判断题 (真):贪心策略的正确性依赖于活动已按结束时间排好序。如果不排序,算法可能会先选择一个结束时间很晚的活动,导致许多其他活动无法被选择,从而得不到最优解。 14. 选择题 (D):这是一个标准的活动选择(或称为区间调度)问题的贪心解法。 15. 选择题 (C):输入数据为(开始时间, 结束时间):(3,5), (1,4), (5,7), (2,6), (8,9)。 1. 按结束时间排序后:(1,4), (3,5), (2,6), (5,7), (8,9)。 2. 选择第一个活动 (1,4)。count=1,current_end_time=4。 3. 下一个活动 (3,5),开始时间 3 < 4,冲突,跳过。 4. 下一个活动 (2,6),开始时间 2 < 4,冲突,跳过。 5. 下一个活动 (5,7),开始时间 5 >= 4,不冲突。选择该活动。count=2,current_end_time=7。 6. 下一个活动 (8,9),开始时间 8 >= 7,不冲突。选择该活动。count=3,current_end_time=9。 最终count为 3。
三、完善程序
(1) 最长上升子序列
这是一个经典的动态规划问题,使用 O(n²) 的时间复杂度解决。
dp[i]表示以a[i]结尾的最长上升子序列的长度。-
状态转移方程:
dp[i] = max(dp[j]) + 1,其中0 <= j < i且a[j] < a[i]。 -
代码逻辑:
- 外层循环
for (int i = 1; i < n; ++i)遍历序列中的每个元素,计算dp[i]。 - 内层循环
for (int j = 0; j < i; ++j)遍历a[i]之前的所有元素a[j]。 - 如果
a[i] > a[j],说明a[i]可以接在以a[j]结尾的上升子序列后面,形成一个更长的序列。此时,我们尝试用dp[j] + 1来更新dp[i]。 max_len用于记录所有dp[i]中的最大值,即为整个序列的 LIS 长度。
- 外层循环
-
题目解析: 16. C: 内层循环需要遍历
i之前的所有元素,所以j的范围是0到i-1,即j < i。 17. A: 要构成上升子序列,当前元素a[i]必须大于之前的某个元素a[j]。 18. B: 如果a[i]可以接在a[j]后面,那么以a[i]结尾的 LIS 长度至少是dp[j] + 1。我们要取所有可能的前驱j中能使dp[i]最大的那一个。 19. B:max_len需要在每次计算完一个dp[i]后,更新全局的最大值,因此使用max函数。
(2) 二分查找
本题要求在一个升序序列中,找到第一个大于等于
x的元素的位置。这是一个二分查找的变种。-
算法思想:
- 维护一个搜索区间
[left, right]。 ans变量用于记录“可能的答案”,初始化为一个哨兵值n。- 当
a[mid] >= x时,mid是一个潜在的答案,我们记录下来ans = mid。但是,可能还有更靠左的(更小的下标)也满足条件,所以我们需要在左半部分[left, mid - 1]继续查找。 - 当
a[mid] < x时,mid以及mid左边的所有元素都小于x,不可能是答案,所以我们必须在右半部分[mid + 1, right]查找。 - 循环条件是
left <= right,确保当left和right相遇时,这个点也能被检查到。
- 维护一个搜索区间
-
题目解析: 20. B:
left <= right是包含端点的二分查找的经典循环条件,能确保搜索区间为空时才退出。 21. C: 当a[mid] >= x时,mid本身就是一个满足条件的答案。我们用ans记下它。 22. B: 既然mid已经是一个可能的答案,我们就要尝试在mid的左边寻找是否有“更早”的答案,所以将搜索区间的右边界缩为mid - 1。 23. C: 当a[mid] < x时,mid以及它左边的所有元素都太小了,不可能是答案。因此,新的搜索区间应该从mid + 1开始。
-
- 1
信息
- ID
- 9962
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 1
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者