2026年蓝桥杯b组答案及参考解析

张开发
2026/4/13 13:06:04 15 分钟阅读

分享文章

2026年蓝桥杯b组答案及参考解析
A.青春常数答案1013101260121012解析送分B.双碳战略答案792264670解析典型的找规律的题目。正常暴力解练笔都动不了。我们首先通过小规模的 nn 来寻找“最少操作次数总和”的规律。当 n1 时状态有 2 种总步数为 1。公式 1×1 。当 n2 时状态有 4 种总步数为 4。公式 2×4 。当 n3 时状态有 8 种总步数为 12。公式 3×12 。由此归纳出通项公式对于 n 盏路灯所有状态的最少操作次数之和为规律找出来了。接下来还需要考虑的是如何计算这么大的指数形式的数的值这里很自然可以想到快速幂模版。// 快速幂函数计算 (base^exp) % mod long long modPow(long long base, long long exp, long long mod) { long long result 1; base % mod; while (exp 0) { if (exp 1) { // 如果 exp 是奇数 result (result * base) % mod; } base (base * base) % mod; exp 1; // exp 右移一位 (除以 2) } return result; }最后输出结果即可。#include iostream using namespace std; int main() { const long long MOD 998244353; const long long n 2026; // 计算公式n * 2^(n-1) % MOD long long power_part modPow(2, n - 1, MOD); long long ans (n % MOD) * power_part % MOD; cout ans endl; return 0; }C.循环右移题目描述给定三个整数 N,X,Y。请计算有多少个长度为 N 的整数数组 A 满足以下条件数组 A 中的每个元素 Ai​ 都满足 X≤Ai​≤Y对于数组 A 中的任意一个连续子数组对其进行一次循环右移操作得到的新子数组与原数组完全一致。循环右移对一个长度为 k 的连续子数组 [B1​,B2​,…,Bk​] 执行一次循环右移操作是指将该子数组变换为 [Bk​,B1​,B2​,...,Bk−1​]即把最后一个元素移到最开头其余元素保持原有顺序依次向后顺延一位。输入格式第一行包含一个整数 T表示测试数据的组数。接下来的 T 行每行包含三个由空格隔开的整数 N,X,Y。输出格式对于每组测试数据输出一行包含一个整数表示满足条件的数组 A 的个数。答案#include iostream using namespace std; int main() { int T; if (cin T) { while (T--) { long long N, X, Y; cin N X Y; long long ans 0; // 核心逻辑数组必须全相等即所有元素取值 v 必须满足 X v Y if (X Y) { ans Y - X 1; } else { ans 0; } cout ans \n; } } return 0; }解析关键就是题目中的条件等价于数组 A 的任意连续子数组中的所有元素都必须相等。D. 蓝桥竞技题目描述小蓝作为电竞俱乐部“蓝桥竞技”的战队经理正面临着一个巨大的管理危机。俱乐部目前签约了 N 种不同位置的职业选手其中第 i 种位置的选手共有 Ai​ 名。为了参加即将举办的“峡谷 5v5”小蓝必须将俱乐部内的所有选手都编入战队不能有任何一人坐冷板凳。根据赛事组委会的严苛规则一支合法的战队必须满足以下条件5 人成团每支战队由且只能由 5 名选手组成。职业互斥同一支战队内的 5 名选手必须来自 5 种完全不同的位置。现在请你帮助小蓝判断在当前的人员数量下是否有一种分组方案能够将所有选手恰好分配完且每支战队都符合参赛规则输入格式第一行包含一个整数 T表示测试用例组数。接下来包含 T 组数据每组数据的格式如下第一行包含一个整数 N表示职业位置的种类数量。第二行包含 N 个整数 A1​,A2​,…,AN​分别表示第 i 种位置的选手人数。输出格式对于每组测试用例如果存在满足条件的分组方案输出 T否则输出 F。答案#include iostream #include vector #include algorithm using namespace std; int main() { int T; cin T; while (T--) { int N; cin N; vectorlong long A(N); long long sum 0; for (int i 0; i N; i) { cin A[i]; sum A[i]; } // 条件1: 至少5种位置 if (N 5) { cout F\n; continue; } // 条件2: 总人数是5的倍数 if (sum % 5 ! 0) { cout F\n; continue; } long long k sum / 5; // 战队数量 // 条件3: 每个位置人数不超过战队数 bool valid true; for (int i 0; i N; i) { if (A[i] k) { valid false; break; } } cout (valid ? T : F) \n; } return 0; }解析每支战队需要 5 个不同位置所以 N ≥ 5否则连一支战队都组不起来。这是一个经典的二分图匹配或多重集合分组问题。看代码自己理解。E. LQ 聚合题目描述2056 年探险队在月球背面的环形山深处发现了一座信号发射塔其核心控制台正在不断闪烁着一串长度为 N 的粒子序列。序列中的每个位置被严格定义为 L 型粒子、Q 型粒子或者因岁月侵蚀而模糊不清的未知状态 ?。这些粒子将被依次射入反应场而反应场的稳定性取决于序列的“LQ 聚合”数量该数量被定义为所有满足 1≤ij≤N 且第 i 个节点为 L、第 j 个节点为 Q 的二元组数量。为了重启这座沉睡的巨塔探险队需要将序列中所有的 ? 修复为确定的 L 或 Q。现在请你计算出在所有可能的修复方案中所能得到的“LQ 聚合”数量的最大值是多少。输入格式第一行输入一个整数 N表示粒子序列的长度。第二行输入一个长度为 N 的字符串仅包含字符 L、Q 和 ?表示当前探测到的粒子序列状态。输出格式输出一个整数表示在将所有 ? 替换为 L 或 Q 后能获得的最大“LQ 聚合”数量。答案及注释#include iostream #include string #include vector #include algorithm using namespace std; int main() { // 优化输入输出效率防止大数据量下超时 ios::sync_with_stdio(false); cin.tie(0); int N; if (!(cin N)) return 0; string s; cin s; // --- 第一步预处理 --- // 1. 统计 ? 的总数用于后续计算右边还有多少个 ? 会变成 Q long long total_unknown 0; for (char c : s) { if (c ?) total_unknown; } // 2. 计算初始状态的分数 // 假设分界线在最左边k0即所有 ? 都暂时看作 Q long long current_pairs 0; long long count_L 0; // 记录当前扫描过的 L 的数量 for (char c : s) { if (c L) { count_L; } else if (c Q || c ?) { // 如果是 Q 或者 ? (暂时看作 Q)它们会与左边所有的 L 形成配对 current_pairs count_L; } } long long max_pairs current_pairs; // 初始化最大值为初始状态 // 3. 预处理后缀 Q 的数量 // suffix_Q[i] 表示从位置 i 到末尾原本就是 Q 的字符数量 vectorlong long suffix_Q(N 1, 0); for (int i N - 1; i 0; i--) { suffix_Q[i] suffix_Q[i 1] (s[i] Q ? 1 : 0); } // --- 第二步贪心移动分界线 --- long long left_L 0; // 分界线左边 L 的总数包括原本的 L 和 ? 变成的 L int unknown_converted_to_L 0; // 已经被变成 L 的 ? 的数量 // 从左到右扫描尝试将分界线向右移动 // 当扫描到 s[i] 为 ? 时意味着分界线跨过它它从 Q 变成了 L for (int i 0; i N; i) { if (s[i] L) { // 遇到原本的 L它被包含在左边的 L 集合中 left_L; } else if (s[i] ?) { // --- 核心逻辑将 s[i] 从 Q 变成 L --- // 1. 失去的贡献 // 它之前作为 Q与左边所有的 L (left_L) 都有配对。 // 现在变成了 L这些配对消失了。 current_pairs - left_L; // 2. 获得的贡献 // 它现在作为 L将与右边所有的 Q 形成新配对。 // 右边的 Q 由两部分组成 // A. 右边原本就是 Q 的字符 (suffix_Q[i 1]) // B. 右边还没被扫描到的 ? (它们依然保持为 Q) long long right_original_Q suffix_Q[i 1]; long long right_unknown_Q (total_unknown - unknown_converted_to_L - 1); current_pairs (right_original_Q right_unknown_Q); // 3. 更新状态变量 left_L; // 这个 ? 现在是 L 了加入左边 L 的计数 unknown_converted_to_L; // 已转换的 ? 数量 1 // 4. 更新最大值 max_pairs max(max_pairs, current_pairs); } } cout max_pairs endl; return 0; }F.应急布线题目描述实验室内小蓝负责维护一个由 N 台计算机组成的局域网络。这些计算机原本通过高速网线互联但随着设备老化目前仅剩 M 条网线还能正常工作。正因如此原本统一的网络分裂成了多个互不相连的通信区域。为了恢复通信小蓝计划架设一种特殊的“应急跳线”来重新连接这些区域。在物理逻辑上只要任意两台计算机之间可以通过残存的网线或新架设的应急跳线建立直接或间接的通路即视为它们之间恢复了连通。小蓝的任务是选定最优的布线方案使得实验室内的所有 N 台计算机重新回到全连通的状态。由于应急跳线的接口会占用计算机宝贵的硬件资源小蓝在制定方案时设定了两个优先层级首先必须确保使用的应急跳线总数达到理论上的最小值其次为了减轻单台计算机的负载压力他要求尽可能平均地分摊这些跳线。具体而言他需要寻找一种方案使得在所有计算机中接入这种应急跳线数量最多的那一台机器其接入的跳线数降到最低。现在请你根据当前网线的残存连接情况计算出实现全连通所需的最少应急跳线数量以及在这一最优前提下单台计算机接入应急跳线数量最大值的最小可能值。输入格式第一行包含两个整数 N 和 M分别表示计算机的总数和目前完好的网线数量。接下来的 M 行每行包含两个整数 a 和 b表示计算机 a 和 b 之间目前仍存在一条完好的网线。输出格式输出一行包含两个由单个空格隔开的整数。第一个整数表示最少需要添加的应急跳线数量第二个整数表示在确保跳线总数最少的前提下单台计算机接入跳线数量最大值的最小可能值。答案及解析#include iostream #include vector #include numeric #include algorithm using namespace std; // 并查集模板 class UnionFind { vectorint parent; vectorint size; // 记录每个连通分量的大小 int components; public: UnionFind(int n) { components n; parent.resize(n); size.resize(n, 1); iota(parent.begin(), parent.end(), 0); } int find(int x) { if (parent[x] ! x) { parent[x] find(parent[x]); } return parent[x]; } void unite(int x, int y) { int rootX find(x); int rootY find(y); if (rootX ! rootY) { // 按大小合并 if (size[rootX] size[rootY]) { parent[rootX] rootY; size[rootY] size[rootX]; } else { parent[rootY] rootX; size[rootX] size[rootY]; } components--; } } int getComponentCount() { return components; } }; int main() { ios::sync_with_stdio(false); cin.tie(0); int N, M; if (!(cin N M)) return 0; UnionFind uf(N); for (int i 0; i M; i) { int a, b; cin a b; uf.unite(a - 1, b - 1); // 转换为0-based } int k uf.getComponentCount(); int min_edges (k 1) ? 0 : k - 1; int min_max_degree; if (k 1) { min_max_degree 0; } else if (k 2) { min_max_degree 1; } else { // k 3 // 我们可以构造一条链来连接所有分量 // 链中间的节点度数为2两端为1 // 所以最大度数为2 min_max_degree 2; } cout min_edges min_max_degree endl; return 0; }G.理想温度题目描述一条工业流水线上排列着 n 个温度传感器。当前各个传感器测得的温度记录在数组 A 中而各传感器对应的理想标准温度记录在数组 B 中即 Ai​ 为第 i 个传感器的当前温度Bi​ 为第 i 个传感器的理想温度。为了让尽可能多的传感器达到理想温度你可以进行一次区域温度补偿操作在流水线上划定一段连续的传感器区间 [l,r]即第 l 个到第 r 个传感器。输入一个温度补偿值 kk 为任意整数使得该区间内所有传感器的当前温度都加上 k。请问在执行完这一次校准操作后最多能使多少个传感器的温度恰好等于其对应的理想标准温度输入格式第一行包含一个整数 n表示传感器的数量。第二行包含 n 个整数 A1​,A2​,…,An​表示各传感器的当前温度。第三行包含 n 个整数 B1​,B2​,…,Bn​表示各传感器对应的理想标准温度。输出格式输出一行包含一个整数表示补偿操作后处于理想温度的传感器最大数量。答案#include iostream #include vector #include algorithm #include unordered_map using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(0); int n; cin n; vectorint A(n), B(n); for (int i 0; i n; i) { cin A[i]; } for (int i 0; i n; i) { cin B[i]; } // 计算差值数组 D vectorint D(n); for (int i 0; i n; i) { D[i] B[i] - A[i]; } // 计算基础分 int base 0; for (int i 0; i n; i) { if (D[i] 0) { base; } } if (base n) { cout n endl; return 0; } int ans base; // 统计每个 k 的出现次数 unordered_mapint, int count; for (int i 0; i n; i) { if (D[i] ! 0) { count[D[i]]; } } // 将 k 值按出现次数从大到小排序 vectorpairint, int candidates(count.begin(), count.end()); sort(candidates.begin(), candidates.end(), [](const pairint, int a, const pairint, int b) { return a.second b.second; }); // 只枚举出现次数最多的前 100 个 k 值 // 这是一个启发式优化通常能过 int limit min((int)candidates.size(), 100); for (int i 0; i limit; i) { int k candidates[i].first; // Kadane 算法 int max_ending_here 0; int max_so_far 0; for (int j 0; j n; j) { int val 0; if (D[j] k) { val 1; } else if (D[j] 0) { val -1; } max_ending_here max(0, max_ending_here val); max_so_far max(max_so_far, max_ending_here); } ans max(ans, base max_so_far); } cout ans endl; return 0; }H.足球训练题目描述小蓝是一支足球队的队长他正在为下一场重要比赛做准备。接下来的 m 天中他每天可以选择一名队员进行训练并且选择之后当天的训练对象不能更换。球队中共有 n 名队员。对于第 i 名队员已知其初始实力值为 ai​天赋值为 bi​。训练规则如下如果小蓝在某一天训练了队员 i则这一天会使该队员的实力值增加 bi​如果一共用 k 天来训练队员 i那么这名队员的最终实力值将变为ai​kbi​。一支队伍的整体实力定义为所有队员最终实力值的乘积即i1∏n​(ai​ki​bi​)其中 ki​ 表示分配给第 i 名队员的训练天数且满足ki​≥0,i1∑n​ki​m小蓝希望通过合理分配这 m 天的训练计划使得队伍的整体实力最大。由于结果可能非常大你只需要输出该最大值对 998244353 取模的结果。答案#include iostream #include vector #include algorithm using namespace std; const long long MOD 998244353; struct Player { long long a, b, c; // c a / b // 用于排序比较边际收益 b / (a k*b) // 比较 b1/(a1k1*b1) 和 b2/(a2k2*b2) // 这里我们只需要比较 b/a 即可因为 k 是固定的 bool operator (const Player other) const { return b * other.a a * other.b; } }; int main() { int n; long long m; cin n m; vectorPlayer players(n); for (int i 0; i n; i) { cin players[i].a players[i].b; players[i].c players[i].a / players[i].b; } // 二分 T floor(1/r) // check(x) 检查当 Tx 时总训练次数是否 m auto check [](long long x) { long long total_days 0; for (int i 0; i n; i) { if (players[i].c x) { total_days x - players[i].c; if (total_days m) return false; } } return true; }; long long l 0, r 2000000000LL, best_T 0; while (l r) { long long mid (l r) / 2; if (check(mid)) { best_T mid; l mid 1; } else { r mid - 1; } } // 根据 best_T 分配训练次数 long long used_days 0; for (int i 0; i n; i) { if (best_T players[i].c) { long long k best_T - players[i].c; players[i].a k * players[i].b; used_days k; } } // 处理剩余天数 long long remaining_days m - used_days; sort(players.begin(), players.end()); // 按边际收益 b/a 降序排序 for (int i 0; i remaining_days; i) { players[i].a players[i].b; } // 计算最终乘积 long long result 1; for (int i 0; i n; i) { result (result * (players[i].a % MOD)) % MOD; } cout result endl; return 0; }希望对你有帮助。

更多文章