洛谷基础计划后期 期末考试 游寄

有些是抄的 chenzhe 发的 pdf.

前言 · 出题方向

讲评 pdf:12测试与评估.pdf

本次考试,考察的是本学期所学的知识,也多了一种在线上比赛中常见的知识——构造题。

第 1 题,素数:难度:简单,J 组第一题,算法:模拟

第 2 题,和树:难度:简单,J 组第二题,算法:图论(最近就在讲这系列知识点)

第 3 题,迷宫:难度:中等,J 组第三题,算法:搜索

第 4 题,数列:难度:中等,J 组第三题,算法:构造(正式赛一般不考)

第 5 题,优秀:难度:较难,J 组第三-第四题,算法:贪心+01 背包

T1

模拟题意即可。

复杂度即为 埃氏筛 的复杂度,O(n\log{\log{n}}),近似于线性。

参考代码(本人写的):

#include <bits/stdc++.h>
using namespace std;
bool T[5000010];
int n;
void input()
{
    cin >> n;
    T[0] = T[1] = 1;
}
bool isRemoved(int x)
{
    return T[x];
}
void remove(int x)
{
    T[x] = 1;
}
void work()
{
    for (int i = 2; i <= n; i++)
    {
        if (!isRemoved(i))
        {
            for (int j = i; j <= n; j += i)
            {
                if (!isRemoved(j))
                {
                    T[j] = 1;
                    printf("%d ", j);
                }
            }
        }
    }
}
int main()
{
    input();
    work();
    return 0;
}

T2

Description

给定一棵树,树有点权,问从根节点1出发有多少条简单路径使得路径上所有节点的权值之和不少于 val.

Solution #1

树是无向的,要建反向边。

模拟深度遍历一棵树的过程,每次遍历时记录走到当前结点的点权和,与val进行比较,统计结果,注意要开long long.

Solution #2

预处理每个点的子树大小,到一个结点发现已经不少于val时,直接加上这个结点的子树大小即可。还可以避免开long long,只不过缺点是码量较大。

T3

难度相当于 CSP-J T3.

Solution 30%

只有一行。此时可以找出第k个墙壁的位置,再找到其右边延伸出去的道路的最右边的位置即可。

Solution 40%

没有道具。直接写普通 dfs 或 bfs.

Solution 70%

以上 30% 与 40% 加起来就可骗到70分。

Solution 100%

看到走迷宫首先想搜索,然后考虑如何处理k个道具。

不妨设 f[x][y] 表示到达了点 (x,y) 之后,能够剩下的最多的道具个数,初始值除了左上角的格点是 k 之外,其余的格点都是 -1。则能够到达的格点数量就是 f[x][y] \ge 0 的数量。

对此进行搜索,搜索时需要剪枝,若到达这个格点的时候道具少于 f[x][y],就没有必要进行后续搜索了。

时间复杂度为\mathcal{O(nmk)}.

注意要剪枝,否则会超时。

T4

什么都不说了 上图。

截屏2022-07-23
构造题中比较入门的内容。

出处:上海某中学高三模拟卷压轴题最后一问。

Description

定义一次操作为:将数列中所有的数值减去任意指定的常数c后取绝对值。
2个问题:

  1. 对于任意长度为n的数列,用不超过n次操作将其全部清零;
  2. 对于长度为n的排列,用\min(n-1,3022)次操作将其全部清零。

4 \le n \le 6,000.

Subtask 1: Solution

首先我们发现,如果一个数列在第m次操作被清零,则第m-1次操作时数列的数值必然全部相等。

则对于问题一,我们可以将问题转化为,用不超过n-1次操作,将所有数字化为相同的数字。更进一步来说,如果每次操作需要让数列中的不同数字的个数下降1,那么在n-1次操作后数列便可以全部相等。

那么如何处理?我们不妨解方程:\lvert a-c \rvert = \lvert b-c \rvert,可得c=\dfrac{a+b}{2}.

这给了我们一个启示,只要每次让c指定为两个元素的平均值即可。

这样,我们在第i次操作,令c[i]=\dfrac{a[i]+a[i+1]}{2}即可,稍加验证可得这样最后得到的数列的值是相等的。
这样,最后一次我们减去数列中的任意元素,即可将数列全部清零。时间复杂度 \mathcal{O(n^2)}.
Subtask 1 解决,获得 30 pts.

Subtask 2: Solution

问题二难度较高。长度为n的数列,且数列中1-n都出现了恰好一遍,其实说明了数列从小到大排序就是长成1, 2, 3, ..., n的样子。由于每次操作是对整个数列进行运算,因而不管数列长得怎么样其实对操作方式
是没有影响的。我们就不妨假设它就是1, 2, 3, ..., n.

n最大是 6000,但是只给了 3022 次操作机会,本质上要求的是每一次让两个原本不相同的数字变得相同,才可以在规定次数内完成。观察样例。

样例中对于数列 1,2,3,4,先用 c[1]=2.5 操作,这样一来就让数列变成了 1.5,0.5,0.5,1.5 的样子,相当于直接让数列中,不同的数字的种类直接少掉一半。此外,我们还能发现,0.5 进行一次c=1的操作之后还是 0.5,但是其他的数字会下降1

暗示了什么?如果我们能一次性直接把数列值域降低一半,那么剩下的操作都交给c=1去解决即可。
这里的做法将n进行了奇偶性的讨论。

n为偶数的时候,不妨令c[1]=\dfrac{n+1}{2},即原来数列的中位数。这样可以把原来1, 2, 3, ..., n的数列变成
\dfrac{n-1}{2},\dfrac{n-3}{2},\dfrac{n-5}{2},\cdots ,\dfrac{3}{2},\dfrac{1}{2},\dfrac{1}{2},\dfrac{3}{2}, \cdots, \dfrac{n-5}{2},\dfrac{n-3}{2},\dfrac{n-1}{2}

这样之后我们对数列进行若干次 c=1 的操作。由于最后所有的数字都会被下降到 \dfrac{1}{2},而且 \dfrac{1}{2} 再怎么操作 c=1 还是 \dfrac{1}{2},在最后一次令 c=\dfrac{1}{2} 即可。

这样操作要多少次呢?\dfrac{n-1}{2}要用\dfrac{n}{2}-1c=1的操作才能下降到1. 也就是说,总共需要操作\dfrac{n}{2}+1次,符合要求。

n为奇数时同理,总操作次数为\dfrac{n+1}{2}+1次,时间复杂度均为\mathcal{O(n)}.

T5

Description

给定一个长度为n的序列,从中选出不超过k个数,要求乘积的末尾0最多。

1\le k \le n \le 300,1\le a_i\le 10^{18}.

Solution

因为在原来没有0的情况下,只有2\times 5才能产生0;所以,一个数字末尾0的个数,取决于将其质因数分解后2与5的个数中较小的一个。

由于乘一个正整数,其质因子2和5的个数是不会下降的,所以说最佳策略就是选k个数。

基本上就是个 0-1背包 板子题。

最后的乘积(product)为p=2^x\times 5^y \times z.

赛后总结

上号一看T1简单,然后发现T2巨坑;
T3T4一看巨难,T5骗分0分完蛋。

寄。

注:本人观点,没有任何现实意义。