2025第十六届蓝桥杯C/C++B组省赛个人题解

现在洛谷可以提交了,这是我的过题情况,测试数据均为洛谷自造,与官方数据可能存在差异,仅供参考。

A 移动距离

题目分数:5分

题目描述

小明初始在二维平面的原点,他想前往坐标 \((233, 666)\)。在移动过程中,他只能采用以下两种移动方式,并且这两种移动方式可以交替、不限次数地使用:

  1. 水平向右移动,即沿着 \(x\) 轴正方向移动一定的距离。
  2. 沿着一个圆心在原点 \((0, 0)\)、以他当前位置到原点的距离为半径的圆的圆周移动,移动方向不限(即顺时针或逆时针移动不限)。

在这种条件下,他到达目的地最少移动多少单位距离?你只需要输出答案四舍五入到整数的结果。

思路
先沿着 x 轴移动原点到目标点的距离,然后再做一个圆周移动,直接到达目标点,赛时大脑大脑短路,对边比邻边应该是tan我写成了sin,0分,正确答案是1576

B 客流量上限

题目分数:5分

题目描述

一家连锁旅馆在全国拥有 \(2025\) 个分店,分别编号为 \(1\)\(2025\)。随着节日临近,总部决定为每家分店设定每日客流量的上限,分别记作 \(A_1, A_2, \dots , A_{2025}\)。这些上限并非随意分配,而是需要满足以下约束条件:

  1. \(A_1, A_2, \dots , A_{2025}\) 必须是 \(1\)\(2025\) 的一个排列,即每个 \(A_i\) 均是 \(1\)\(2025\) 之间的整数,且所有 \(A_i\) 互不相同。
  2. 对于任意分店 \(i\)\(j\)\(1 \leq i, j \leq 2025\)\(i\) 可等于 \(j\)),它们的客流量上限 \(A_i\)\(A_j\) 的乘积不得超过 \(i \times j + 2025\)

这些约束旨在平衡各分店客流压力,确保服务质量和运营稳定性。

现在,请你计算这样的分配方案究竟有多少种。由于答案可能很大,你只需输出其对 \(10^9 + 7\) 取余后的结果即可。

思路
根本读不懂题,感觉这是最难的一道,赛时直接蒙了个20253取模,正确答案是21012取模

C 可分解的正整数

题目分数:10分

题目描述

定义一种特殊的整数序列,这种序列由连续递增的整数组成,并满足以下条件:

  1. 序列长度至少为 \(3\)
  2. 序列中的数字是连续递增的整数(即相邻元素之差为 \(1\)),可以包括正整数、负整数或 \(0\)

例如,\([1, 2, 3]\)\([4, 5, 6, 7]\)\([−1, 0, 1]\) 是符合条件的序列,而 \([1, 2]\)(长度不足)和 \([1, 2, 4]\)(不连续)不符合要求。

现给定一组包含 \(N\) 个正整数的数据 \(A_1, A_2, \dots , A_N\)。如果某个 \(A_i\) 能够表示为符合上述条件的连续整数序列中所有元素的和,则称 \(A_i\) 是可分解的。

请你统计这组数据中可分解的正整数的数量。

输入格式

输入的第一行包含一个正整数 \(N\),表示数据的个数。

第二行包含 \(N\) 个正整数 \(A_1, A_2, \dots , A_N\),表示需要判断是否可分解的正整数序列。

输出格式

输出一个整数,表示给定数据中可分解的正整数的数量。

输入输出样例

输入 #1

3
3 6 15

输出 #1

3

说明/提示

样例说明

  • \(A_i = 3\) 是可分解的,因为 \([0, 1, 2]\) 的和为 \(0 + 1 + 2 = 3\)
  • \(A_i = 6\) 是可分解的,因为 \([1, 2, 3]\) 的和为 \(1 + 2 + 3 = 6\)
  • \(A_i = 15\) 是可分解的,因为 \([4, 5, 6]\) 的和为 \(4 + 5 + 6 = 15\)

所以可分解的正整数的数量为 \(3\)

评测用例规模与约定

  • 对于 \(30\%\) 的评测用例,\(1 \leq N \leq 100\)\(1 \leq A_i \leq 100\)
  • 对于 \(100\%\) 的评测用例,\(1 \leq N \leq 10^5\)\(1 \leq A_i \leq 10^9\)

思路
刚开始想推个公式,后来手动模拟发现出了1以外的正整数都可以,因为可以像:2 = -1 + 0 + 1 + 2 这样抵消掉,而 1 = 0 + 1,序列长度为2不符合题意。

#include <bits/stdc++.h>

using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int n;
    cin >> n;
    int res = 0;
    for (int i = 0; i < n; i++) {
        int t;
        cin >> t;
        if (t != 1) res++;
    }
    cout << res;
    return 0;
}

D 产值调整

题目分数:10分

题目描述

偏远的小镇上,三兄弟共同经营着一家小型矿业公司“兄弟矿业”。公司旗下有三座矿山:金矿、银矿和铜矿,它们的初始产值分别用非负整数 \(A\)\(B\)\(C\) 表示。这些矿山的产出是小镇经济的核心,支撑着三兄弟和许多矿工家庭的生计。

然而,各矿山的产值波动剧烈,有时金矿收益高而银矿、铜矿低迷,有时则相反。这种不稳定性让公司收入难以预测,也常引发兄弟间的争执。为了稳定经营,三兄弟设计了一个公平的产值调整策略,每年执行一次,每次调整时,将根据当前的产值 \(A\)\(B\)\(C\),计算新产值:

  1. 金矿新产值:\(A'=\lfloor \dfrac{B+C}{2} \rfloor\)
  2. 银矿新产值:\(B'=\lfloor \dfrac{A+C}{2} \rfloor\)
  3. 铜矿新产值:\(C'=\lfloor \dfrac{A+B}{2} \rfloor\)

其中,\(\lfloor \rfloor\) 表示向下取整。例如,\(\lfloor 3.7\rfloor = 3\)\(\lfloor 5.2\rfloor = 5\)

计算出 \(A'\)\(B'\)\(C'\) 后,同时更新:\(A\) 变为 \(A'\)\(B\) 变为 \(B'\)\(C\) 变为 \(C'\),作为下一年调整的基础。

三兄弟认为这个方法能平衡产值波动,于是计划连续执行 \(K\) 次调整。现在,请你帮他们计算,经过 \(K\) 次调整后,金矿、银矿和铜矿的产值分别是多少。

输入格式

输入的第一行包含一个整数 \(T\),表示测试用例的数量。

接下来的 \(T\) 行,每行包含四个整数 \(A,B,C,K\),分别表示金矿、银矿和铜矿的初始产值,以及需要执行的调整次数。

输出格式

对于每个测试用例,输出一行,包含三个整数,表示经过 \(K\) 次调整后金矿、银矿和铜矿的产值,用空格分隔。

输入输出样例

输入 #1

2
10 20 30 1
5 5 5 3

输出 #1

25 20 15
5 5 5

说明/提示

评测用例规模与约定

  • 对于 \(30\%\) 的评测用例,\(1 \leq T \leq 100\)\(1 \leq A, B, C, K \leq 10^5\)
  • 对于 \(100\%\) 的评测用例,\(1 \leq T \leq 10^5\)\(1 \leq A, B, C, K \leq 10^9\)

思路
想推个结果公式,没推出来,然后直接模拟,用rand跑了一下,发现三个数最后都会相等,相等的时候无论多少次调整都还是不变,但是竟然没想到可以break;最大的失误,只拿了30%。

#include <bits/stdc++.h>

using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int t;
    cin >> t;
    while (t--) {
        long long a, b, c, k, x, y, z;
        cin >> a >> b >> c >> k;
        x = a, y = b, z = c;
        for (int i = 0; i < k; i++) {
            x = (b + c) >> 1, y = (a + c) >> 1, z = (a + b) >> 1;
            a = x, b = y, c = z;
        }
        cout << a << ' ' << b << ' '<< c << '\n';
    }
    return 0;
}

E 画展布置

题目分数:15分

题目描述

画展策展人小蓝和助理小桥为即将举办的画展准备了 \(N\) 幅画作,其艺术价值分别为 \(A_1, A_2, \dots , A_N\)。他们需要从这 \(N\) 幅画中挑选 \(M\) 幅,并按照一定顺序布置在展厅的 \(M\) 个位置上。如果随意挑选和排列,艺术价值的变化可能会过于突兀,导致观众的观展体验不够流畅。

为了优化布置,他们查阅了《画展布置指南》。指南指出,理想的画展应使观众在欣赏画作时,艺术价值的过渡尽量平缓。指南建议,选择并排列 \(M\) 幅画,应使艺术价值的变化程度通过一个数值 \(L\) 来衡量,且该值越小越好。数值 \(L\) 的定义为:

\[L=\sum_{i=1}^{M-1} |B_{i+1}^2-B_i^2| \]

其中 \(B_i\) 表示展厅第 \(i\) 个位置上画作的艺术价值。

现在,他们希望通过精心挑选和排列这 \(M\) 幅画作,使 \(L\) 达到最小值,以提升画展的整体协调性。请你帮他们计算出这个最小值是多少。

输入格式

输入共两行。

第一行包含两个正整数 \(N\)\(M\),分别表示画作的总数和需要挑选的画作数量。

第二行包含 \(N\) 个正整数 \(A_1, A_2, \dots , A_N\),表示每幅画作的艺术价值。

输出格式

输出一个整数,表示 \(L\) 的最小值。

输入输出样例

输入 #1

4 2
1 5 2 4

输出 #1

3

说明/提示

评测用例规模与约定

  • 对于 \(40\%\) 的评测用例,\(2 \leq M \leq N \leq 10^3\)\(1 \leq A_i \leq 10^3\)
  • 对于 \(100\%\) 的评测用例,\(2 \leq M \leq N \leq 10^5\)\(1 \leq A_i \leq 10^5\)

思路
差值的绝对值求和,一眼排序+滑动窗口,题目数据范围不是很大,直接偷懒直接用deque写了。

#include <bits/stdc++.h>

using namespace std;
const int N = 1e5 + 10;
int a[N];
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int n, m;
    cin >> n >> m;
    for (int i = 0; i < n; i++) cin >> a[i];
    sort(a, a + n);
    deque<int> q;
    q.push_back(a[0]);
    long long res = 0, sum = 0;
    for (int i = 1; i < m; i++) {
        sum += abs(q.back() * q.back() - a[i] * a[i]);
        q.push_back(a[i]);
    }
    res = sum;
    for (int i = m; i < n; i++) {
        sum += abs(q.back() * q.back() - a[i] * a[i]);
        int t = q.front();
        q.pop_front();
        sum -= abs(t * t - q.front() * q.front());
        q.push_back(a[i]);
        res = min(res, sum);
    }
    cout << res;
    return 0;
}

F 水质检测

题目分数:15分

题目描述

小明需要在一条 \(2 \times n\) 的河床上铺设水质检测器。在他铺设之前,河床上已经存在一些检测器。如果两个检测器上下或者左右相邻,那么这两个检测器就是互相连通的。连通具有传递性,即如果 \(A\)\(B\) 连通,\(B\)\(C\) 连通,那么 \(A\)\(C\) 也连通。现在他需要在河床上增加铺设一些检测器使得所有的检测器都互相连通。他想知道最少需要增加铺设多少个检测器?

输入格式

输入共两行,表示一个 \(2 \times n\) 的河床。

每行一个长度为 \(n\) 的字符串,仅包含 #.,其中 # 表示已经存在的检测器,. 表示空白。

输出格式

输出共 \(1\) 行,一个整数表示答案。

输入输出样例

输入 #1

.##.....#
.#.#.#...

输出 #1

5

说明/提示

样例说明

其中一种方案:

.###....#
.#.######

增加了 5 个检测器。

评测用例规模与约定

对于 \(100\%\) 的评测用例,保证 \(n \leq 1000000\)

思路
经典的线性dp,去年没考dp,今年可算考了,赛时代码写的比较丑陋,有优化空间。

#include <bits/stdc++.h>

using namespace std;
const int N = 1e6 + 10;
string s[2];
int f[2][N];
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    cin >> s[0] >> s[1];
    int n = s[0].size();
    int l = n - 1, r = 0;
    for (int i = 0; i < n; i++) {
        if (s[0][i] == '#' || s[1][i] == '#') {
            l = min(l, i);
            r = max(r, i);
        }
    }
    if (s[0][l] == '.') f[0][l] = 1;
    if (s[1][l] == '.') f[1][l] = 1;
    for (int i = l + 1; i <= r; i++) {
        int x = 0, y = 0;
        if (s[0][i] == '.') x = 1;
        if (s[1][i] == '.') y = 1;
        f[0][i] = min(f[0][i - 1], f[1][i - 1] + y);
        f[1][i] = min(f[1][i - 1], f[0][i - 1] + x);
        f[0][i] += x;
        f[1][i] += y;
    }
    cout << min(f[0][r], f[1][r]);
    return 0;
}

G 生产车间

题目分数:20分

题目描述

小明正在改造一个生产车间的生产流水线。这个车间共有 \(n\) 台设备,构成以 \(1\) 为根结点的一棵树,结点 \(i\) 有权值 \(w_i\)。其中叶节点的权值 \(w_i\) 表示每单位时间将产出 \(w_i\) 单位的材料并送往父结点,根结点的权值 \(w_i\) 表示每单位时间内能打包多少单位成品,其他结点的权值 \(w_i\) 表示每单位时间最多能加工 \(w_i\) 单位的材料并送往父结点。

由于当前生产线中某些结点存在产能不够的问题导致生产线无法正常运行,即存在某些结点每单位时间收到的材料超过了当前结点的加工能力上限。小明计划删除一些结点使得所有结点都能正常运行。他想知道删除一些结点后根结点每单位时间内最多能打包多少单位的成品?

输入格式

输入共 \(n + 1\) 行。

第一行为一个正整数 \(n\)

第二行为 \(n\) 个由空格分开的正整数 \(w_1,w_2, \dots,w_n\)

后面 \(n - 1\) 行,每行两个整数表示树上的一条边连接的两个结点。

输出格式

输出共一行,一个整数代表答案。

输入输出样例

输入 #1

9
9 7 3 7 1 6 2 2 7
1 2
1 3
2 4
2 5
2 6
6 7
6 8
6 9

输出 #1

8

说明/提示

样例说明

删掉结点 \(4\)\(9\) 后生产线满足条件,根结点 \(1\) 每单位时间将打包出 \(8\) 单位的成品。

评测用例规模与约定

  • 对于 \(20\%\) 的评测用例,\(2 \leq n \leq 100\)
  • 对于 \(100\%\) 的评测用例,\(2 \leq n \leq 1000\)\(1\leq w_i \leq 1000\)

思路
树上问题,直接开蒙,考虑到很有可能修改后并不影响总产值,所以直接输出根节点,洛谷样例竟然能过一半,有点离谱,不知道蓝桥的样例怎么样,最能骗分的一集。

H 装修报价

题目分数:20分

题目描述

老王计划装修房子,于是联系了一家装修公司。该公司有一套自动报价系统,只需用户提供 \(N\) 项装修相关费用 \(A_1, A_2, \dots , A_N\),系统便会根据这些费用生成最终的报价。

然而,当老王提交数据后,他发现这套系统的运作方式并不透明:系统只会给出一个最终报价,而不会公开任何运算过程或中间步骤。

公司对此解释称,这套系统会依据某种内部算法,在每对相邻数字之间插入 \(+\)(加法)、\(-\)(减法)或 \(\oplus\)(异或)运算符,并按照特定优先级规则计算结果:异或运算优先级最高,其次是加减。但由于保密性,具体的运算符组合以及中间过程都不会对外公开。

为了验证系统报价是否合理,老王决定模拟其运作方式,尝试每种可能的运算符组合,计算出所有可能出现的结果的总和。如果最终报价明显超出这个范围,他就有理由怀疑系统存在异常或误差。只是老王年事已高,手动计算颇为吃力,便向你求助。

现在,请你帮老王算出所有可能的结果的总和。由于该总和可能很大,你只需提供其对 \(10^9+7\) 取余后的结果即可。

输入格式

第一行输入一个整数 \(N\),表示装修相关费用的项数。

第二行输入 \(N\) 个非负整数 \(A_1, A_2, \dots , A_N\),表示各项费用。

输出格式

输出一个整数,表示所有可能的总和对 \(10^9 + 7\) 取余后的结果。

输入输出样例

输入 #1

3
0 2 5

输出 #1

11

说明/提示

对于输入样例中的三个数 \(A = [0, 2, 5]\),所有可能的运算符组合共有 \(9\) 种。计算结果如下:

\[0 \oplus 2 \oplus 5 = 7 \]

\[0 \oplus 2 + 5 = 7 \]

\[0 \oplus 2 - 5 = -3 \]

\[0 + 2 \oplus 5 = 7 \]

\[0 + 2 + 5 = 7 \]

\[0 + 2 - 5 = -3 \]

\[0 - 2 \oplus 5 = -7 \]

\[0 - 2 + 5 = 3 \]

\[0 - 2 - 5 = -7 \]

所有结果的总和为:

\[7 + 7 + (-3) + 7 + 7 + (-3) + (-7) + 3 + (-7) = 11 \]

\(11\)\(10^9 + 7\) 取余后的值依然为 \(11\),因此,输出结果为 \(11\)

评测用例规模与约定

  • 对于 \(30\%\) 的评测用例,\(1 \leq N \leq 13\)\(0 \leq A_i \leq 10^3\)
  • 对于 \(60\%\) 的评测用例,\(1 \leq N \leq 10^3\)\(0 \leq A_i \leq 10^5\)
  • 对于 \(100\%\) 的评测用例,\(1 \leq N \leq 10^5\)\(0 \leq A_i \leq 10^9\)

思路
能看出来是组合数学,但是我不会,直接写了个dfs,只过了洛谷10%样例。

#include <bits/stdc++.h>

using namespace std;
const int N = 1e5 + 10;
int n, a[N];
long long res = 0;
void dfs(int u, long long sum, long long last) {
    if (u == n) {
        res += sum;
        return;
    }
    if (last >= 0) dfs(u + 1, sum - last + (last ^ a[u]), last ^ a[u]);
    else dfs(u + 1, sum - last - ((-last) ^ a[u]), last ^ a[u]);
    dfs(u + 1, sum + a[u], a[u]);
    dfs(u + 1, sum - a[u], -a[u]);
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    cin >> n;
    for (int i = 0; i < n; i++) cin >> a[i];
    dfs(1, a[0], a[0]);
    cout << res;
    return 0;
}

总结

对比去年蓝桥杯,这次暴力能力上升了,我是暴力大王,哈哈。
但还是有一些不足,发挥不是很稳定,洛谷估分55,希望能拿到国赛门票吧。

posted @ 2025-04-19 12:13  风行叶落  阅读(485)  评论(0)    收藏  举报