第十六届蓝桥杯大赛软件赛省赛 C/C++ 大学B组 [京津冀]
由于官方没有公布题目的数据, 所以代码仅供参考
1. 密密摆放
题目链接:P12337 [蓝桥杯 2025 省 AB/Python B 第二场] 密密摆放 - 洛谷
题目描述
小蓝有一个大箱子,内部的长宽高分别是 200、250、240(单位:毫米),他要用这个大箱子来放一些同样大小的小盒子,小盒子的外部长宽高分别是 30、40、50(单位:毫米)。小盒子允许从各个方向旋转(包括可以平放和倒放)。
请问小蓝最多可以在一个大箱子里面放多少个小盒子。
代码如下:
#include <bits/stdc++.h>
using namespace std;
int solve(int i,int j, int k){return i*j*k;
}
int main() {int ans=solve(200,250,240)/solve(30,40,50);cout<<ans<<endl;return 0;
}
2. 脉冲强度之和
题目描述
在蓝桥电子工坊,工程师小蓝正在设计一款智能脉冲生成器,用于驱动一种新型设备。该设备的运行依赖于特定的脉冲强度,用正整数 p 表示,其必须满足以下三个条件:可由连续 10 个正整数之和组成:即存在一个正整数 k,使得脉冲强度 p=k+(k+1)+(k+2)+⋯+(k+9)。
各个数位上的数字都相同:例如 1111、22222、333333 等。
数值不超过 20255202:即 1≤p≤20255202。
通过计算所有符合条件的脉冲强度之和,小蓝能够优化设备运行模式。对此,请帮助他计算这一总和。
解题思路:
1. p=k+(k+1)+(k+2)+⋯+(k+9) => p=(k+k+9)*10/2=10*k+45
2. 解 p=10*k+45, 看k有没有解, 就能验证条件1了
3. 接着验证p的每一位是否相等
4. 按顺序枚举p, 把所有符合条件的p累加起来
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int maxP=20255202;
bool solve(long long p){string s=to_string(p); bool f=false;for(char c:s){if(c!=s[0]){f=true;break;}}return f;
}
int main(){long long ans=0;for(long long k=1;;k++){long long p=10*k+45; if (p > maxP) break;if(!solve(p)) ans+=p;}cout<<ans<<endl;return 0;
}
3. 25 之和
题目描述
小蓝最近对求和很着迷,给定一个正整数 n,他想求从 n 开始的连续 25 个整数的和,即 n+(n+1)+(n+2)+⋯+(n+24),请帮帮他吧。
输入格式
输入一行包含一个正整数 n。
代码如下:
#include <bits/stdc++.h>
using namespace std;
int main() {int n; cin>>n;long long ans =25*(n+(n+24))/2; cout<<ans<<endl;return 0;
}
4. 旗帜
小蓝要画一个 LANQIAO 图形,并把这个图形做成一个旗帜。图形的形状为一个 h×w 的矩形,其中 h 表示图形的高,w 表示图形的宽。当 h=5,w=10 时,图形如下所示:
LANQIAOLAN
ANQIAOLANQ
NQIAOLANQI
QIAOLANQIA
IAOLANQIAO
图形的规律是:第一行用
LANQIAO
重复填入,第二行开始,每行向左移动一个字符,用LANQIAO
重复填入。小蓝需要把图形中的每个字母都剪出来,以粘贴到旗帜上,他想知道,给定图形的高和宽,图形中有多少个
A
。
代码如下:
#include <bits/stdc++.h>
using namespace std;
int main()
{int h, w;cin >> h >> w;string s = "LANQIAO";int ans = 0;for (int i = 0; i < h; i++){for (int j = 0; j < w; j++){if (s[(i + j) % 7] == 'A'){ans++;}}}cout << ans<<endl;return 0;
}
5. 数列差分
题目描述:
小蓝有两个长度均为 n 的数列 A={a1,a2,⋯,an} 和 B={b1,b2,⋯,bn},将两个数列作差定义为 C=A−B={c1=a1−b1,c2=a2−b2,⋯,cn=an−bn}。小蓝将对数列 B 进行若干次操作,每次操作可以将数列 B 中的任意一个数更改为任意一个整数。在进行完所有操作后,小蓝可以按任意顺序将数列 B 重排,之后再计算数列 C。小蓝想知道,最少操作多少次可以使得数列 C 中的所有数都为正整数。
代码如下:
#include <bits/stdc++.h>
using namespace std;
int main() {int n; cin>>n; vector<long long> a(n); vector<long long> b(n);for(int i=0;i<n;i++) cin>>a[i];for(int i=0;i<n;i++) cin>>b[i];sort(a.begin(),a.end()); sort(b.begin(),b.end());int i=0; int j=0,ans=0;while(i<n&&j<n){if(a[i]>b[j]){i++;j++;ans++;}else{i++;}}cout<<(n-ans)<<endl;return 0;
}
6. 树上寻宝
小蓝正在一棵含有 n 个结点的树的根结点 1 上,他准备在这棵树上寻宝。结点 i 上有一个物品,价值为 wi。然而,小蓝每次寻宝只能从根节点出发走不超过 k 步,每步只能选择走 1 条边或者 2 条边,之后会自动拾取最终停留的结点上的物品并被传送回根结点。请求出小蓝最终能获得的物品的总价值。
输入格式
输入的第一行包含两个正整数 n,k,用一个空格分隔。
第二行包含 n 个正整数 w1,w2,⋯,wn,相邻整数之间使用一个空格分隔。
接下来 n−1 行,每行包含两个正整数 ui,vi,用一个空格分隔,表示结点 ui 和结点 vi 之间有一条边。
输出格式
输出一行包含一个整数表示答案。
解题思路:bfs, 定义d[i]: 节点i到根节点的边数距离, 每步选择的时候, 能走2就不会走1
⌈d[i]/2⌉<=k, d[i]<=2*k
#include <bits/stdc++.h>
using namespace std;
int main() {int n;long long k;cin >> n >> k;vector<long long> w(n+1);for (int i = 1; i <= n; i++) {cin >> w[i];}vector<vector<int>> grap(n+1);for (int i = 0; i < n-1; i++) {int u, v;cin >> u >> v;grap[u].push_back(v);grap[v].push_back(u);}vector<int> d(n+1, -1);stack<int> st;d[1] = 0;st.push(1);while (!st.empty()) {int u = st.top(); st.pop();for (int v : grap[u]) {if (d[v] == -1) {d[v] = d[u] + 1;st.push(v);}}}long long ans = 0;long long maxD = 2 * k;for (int i = 1; i <= n; i++) {if (d[i] != -1 && d[i] <= maxD) {ans += w[i];}}cout << ans << endl;return 0;
}
7. 破解信息
在遥远的未来,星际旅行已经成为常态。宇航员小蓝在一次探险任务中,意外发现了一个古老的太空遗迹。遗迹中存放着一个数据存储器,里面记录着一段加密的信息。经过初步分析,小蓝发现这段信息可以被表示为一个字符串 S,而解密的关键,在于找出 S 中字典序最大的回文子序列。
- 子序列:指从原字符串中抽取若干个字符(可以不连续),按照它们在原字符串中的相对顺序排列所形成的新序列。例如,对于字符串
abc
,其子序列包括a
、b
、c
、ab
、ac
、bc
和abc
。- 字典序:指字符串按照字典中的排序规则比较大小的方式。对于两个字符串,从左到右逐字符比较,先出现较大字符的字符串字典序更大;若比较到某个字符串结束仍未找到不同的字符,则较短的字符串字典序较小。例如,
abc
<abd
,而ab
<abc
。现在,请你从字符串 S 中,找出字典序最大的回文子序列,帮助小蓝解开这段来自星际文明的信息。
输入格式
输入一行包含一个字符串 S,表示加密的信息。
输出格式
输出一行包含一个字符串,表示 S 中字典序最大的回文子序列
解题思路:统计字符串中字典序最大的字符, 然后统计其出现次数。
不管是奇数次和偶数次都是回文的。
#include<bits/stdc++.h>
using namespace std;
int main()
{string s;cin >> s;char a=*max_element(s.begin(),s.end()); int count=0;for(char c:s){if(c==a) count++;} string ans;for(int i=0;i<count;i++){ans+=a;}cout<<ans<<endl;return 0;
}
8.翻转硬币
题目描述
给定 n 行 m 列共 n×m 个硬币,对于任意一个硬币,我们将其价值视为与其相邻(指上、下、左、右相邻)的硬币中与其正反相同的硬币数的平方。
你可以进行任意次操作,每次可以选择任意一行并将该行的硬币全部翻转。
求所有硬币的价值之和最大可能是多少。
输入格式
输入的第一行包含两个正整数 n,m,用一个空格分隔。
接下来 n 行,每行包含 m 个 0 或 1,表示给定的 n×m 个硬币。
输出格式
输出一行包含一个整数表示答案。
解题思路:这道题是一道DP题, 但是无所谓啊,我们直接写暴力(注:追求前7题满分,最后一题直接打个暴力),欺骗自己AK了
#include <bits/stdc++.h>
using namespace std;
const int dx[4] = {-1, 1, 0, 0};
const int dy[4] = {0, 0, -1, 1};
int main(){int n, m;cin >> n >> m;vector<vector<int>> a(n, vector<int>(m));for(int i = 0; i < n; i++){string s;cin >> s; for(int j = 0; j < m; j++){a[i][j] = s[j] - '0';}}long long ans = 0;int maxNum = 1 << n;for(int k = 0; k < maxNum; k++){int g[20][20];for(int i = 0; i < n; i++){bool f = (k >> i) & 1;for(int j = 0; j < m; j++){g[i][j] = a[i][j] ^ (f ? 1 : 0);}}long long total = 0;for(int i = 0; i < n; i++){for(int j = 0; j < m; j++){int count = 0;for(int d = 0; d < 4; d++){int ni = i + dx[d];int nj = j + dy[d];if(ni >= 0 && ni < n && nj >= 0 && nj < m){if(g[ni][nj] == g[i][j]) {count++;}}}total += (long long)count * count;}}ans = max(ans, total);}cout << ans << endl;return 0;
}
感谢大家的点赞和关注,你们的支持是我创作的动力!
吐槽:难道是上次出题太难了, 这次就....