第十二届蓝桥杯大赛模拟赛(第二期,已更新题解)
莫名感觉模拟赛永远比正赛简单亿点点
第一题
问题描述 :
小明要用二进制来表示 1 到 10000 的所有整数,要求不同的整数用不同的二进制数表示,请问,为了表示 1 到 10000 的所有整数,至少需要多少个二进制位?
答案:14
\(2^{14} > 10000\)
第二题
问题描述 :
请问在 1 到 2020 中,有多少个数既是 4 的整数倍,又是 6 的整数倍。
答案:168
暴力遍历即可
第三题
问题描述 :
请问有多少个序列满足下面的条件:
- 序列的长度为 5。
- 序列中的每个数都是 1 到 10 之间的整数。
- 序列中后面的数大于等于前面的数。
答案:2002
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int a[10];
int cnt;
void dfs(int pos) {
if (pos == 6) {
cnt++;
return;
}
for (int i = 1; i <= 10; ++i)
if (a[pos - 1] <= i) a[pos] = i, dfs(pos + 1);
}
int main() {
ios_base::sync_with_stdio(false), cin.tie(0);
dfs(1);
cout << cnt;
return 0;
}
第四题
问题描述 :
一个无向图包含 2020 条边,如果图中没有自环和重边,请问最少包含多少个结点?
答案:65
n * ( n - 1 ) / 2
第五题
问题描述:
两个字母之间的距离定义为它们在字母表中位置的距离。例如 A 和 C 的距离为 2,L 和 Q 的距离为 5。对于一个字符串,我们称字符串中两两字符之间的距离之和为字符串的内部距离。 例如:ZOO 的内部距离为 22,其中 Z 和 O 的距离为 11。 请问,LANQIAO 的内部距离是多少?
答案:转化为数字内部暴力循环累加
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int a[7], sum[7], res;
string str;
int main() {
ios_base::sync_with_stdio(false), cin.tie(0);
cin >> str;
for (int i = 0; i < str.size(); i++)
a[i] = str[i] - 'A';
for (int i = 0; i < str.size() - 1; i++)
for (int j = i + 1; j < str.size(); j++)
res += abs(a[j] - a[i]);
cout << res << endl;
return 0;
}
第六题开始为编程题
第六题
问题描述
现在时间是 a 点 b 分,请问 t 分钟后,是几点几分?
输入格式
输入的第一行包含一个整数 a。
第二行包含一个整数 b。
第三行包含一个整数 t。
输出格式
输出第一行包含一个整数,表示结果是几点。
第二行包含一个整数,表示结果是几分。
样例输入
3
20
165
样例输出
6
5
样例输入
3
20
175
样例输出
6
15
数据规模和约定
对于所有评测用例,\(0 <= a <= 23, 0 <= b <= 59, 0 <= t\), t 分钟后还是在当天。
简答累加取余操作
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int main() {
ios_base::sync_with_stdio(false), cin.tie(0);
int a, b, t;
cin >> a >> b >> t;
b += t;
cout << (a + b / 60) % 24 << '\n'
<< b % 60;
return 0;
}
第七题
问题描述:
给定一个平行四边形的底边长度 l 和高度 h,求平行四边形的面积。
输入格式
输入的第一行包含一个整数 l,表示平行四边形的底边长度。
第二行包含一个整数 h,表示平行四边形的高。
输出格式
输出一个整数,表示平行四边形的面积。
(提示:底边长度和高都是整数的平行四边形面积为整数)
样例输入
2
7
样例输出
14
数据规模和约定
对于所有评测用例,\(1 <= l, h <= 100\)。
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int main() {
ios_base::sync_with_stdio(false), cin.tie(0);
int l, h;
cin >> l >> h;
cout << l * h << "\n";
return 0;
}
第八题
问题描述:
小蓝有一张黑白图像,由 n * m 个像素组成,其中从上到下共 n 行,每行从左到右 m 列。每个像素由一个 0 到 255 之间的灰度值表示。
现在,小蓝准备对图像进行模糊操作;
操作的方法为: 对于每个像素,将以它为中心 3 * 3 区域内的所有像素(可能是 9 个像素或少于 9 个像素)求和后除以这个范围内的像素个数(取下整),得到的值就是模糊后的结果。
请注意每个像素都要用原图中的灰度值计算求和。
输入格式
输入的第一行包含两个整数 n, m。
第 2 行到第 n + 1 行每行包含 m 个整数,表示每个像素的灰度值,相邻整数之间用一个空格分隔。
输出格式
输出 n 行,每行 m 个整数,相邻整数之间用空格分隔,表示模糊后的图像。
样例输入
3 4
0 0 0 255
0 0 255 0
0 30 255 255
样例输出
0 42 85 127
5 60 116 170
7 90 132 191
数据规模和约定
对于所有评测用例,\(1 <= n, m <= 100\)。
#include <iostream>
using namespace std;
const int N = 110;
int a[N][N], b[N][N];
int m, n;
int main() {
cin >> n >> m;
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
scanf("%d", &a[i][j]);
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++) {
int cnt = 1;
int res = a[i][j];
if (i > 0)
res += a[i - 1][j], cnt++;
if (i < n - 1)
res += a[i + 1][j], cnt++;
if (j > 0)
res += a[i][j - 1], cnt++;
if (j < m - 1)
res += a[i][j + 1], cnt++;
if (i > 0 && j > 0)
res += a[i - 1][j - 1], cnt++;
if (i > 0 && j < m - 1)
res += a[i - 1][j + 1], cnt++;
if (i < n - 1 && j > 0)
res += a[i + 1][j - 1], cnt++;
if (i < n - 1 && j < m - 1)
res += a[i + 1][j + 1], cnt++;
b[i][j] = res / cnt;
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
printf("%d ", b[i][j]);
}
puts("");
}
return 0;
}
第九题
问题描述:
小蓝负责花园的灌溉工作。花园可以看成一个 n 行 m 列的方格图形。中间有一部分位置上安装有出水管。小蓝可以控制一个按钮同时打开所有的出水管,打开时,有出水管的位置可以被认为已经灌溉好每经过一分钟,水就会向四面扩展一个方格,被扩展到的方格可以被认为已经灌溉好。即如果前一分钟某一个方格被灌溉好,则下一分钟它上下左右的四个方格也被灌溉好。给定花园水管的位置,请问 k 分钟后,有多少个方格被灌溉好?
输入格式
输入的第一行包含两个整数 n, m。
第二行包含一个整数 t,表示出水管的数量。
接下来 t 行描述出水管的位置,其中第 i 行包含两个数 r, c 表示第 r 行第 c 列有一个排水管。
接下来一行包含一个整数 k。
输出格式
输出一个整数,表示答案。
样例输入
3 6
2
2 2
3 4
1
样例输出
9
样例说明
用1表示灌溉到,0表示未灌溉到。
打开水管时:
000000
010000
000100
1分钟后:
010000
111100
011110
共有9个方格被灌溉好。
数据规模和约定
对于所有评测用例,\(1 <= n, m <= 100, 1 <= t <= 10, 1 <= k <= 100\)。
// DFS 版本
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int a[110][110] = {0};
int n, m, t, k;
int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
void dfs(int x, int y, int time) {
if (time == k) return;
// cout << x << " " << y << '\n';
for (int i = 0; i < 4; ++i) {
int nx = x + dx[i], ny = y + dy[i];
if (nx < 1 || nx > n || ny < 1 || ny > m) continue;
a[nx][ny] = 1;
dfs(nx, ny, time + 1);
}
}
int main() {
ios_base::sync_with_stdio(false), cin.tie(0);
cin >> n >> m >> t;
vector<pair<int, int>> mp;
for (int i = 0, x, y; i < t; ++i) {
cin >> x >> y;
a[x][y] = 1;
mp.push_back({x, y});
}
// cout << mp.front().first << " " << mp.front().second << "\n";
cin >> k;
for (auto c : mp) {
// cout << c.first << " " << c.second << endl;
dfs(c.first, c.second, 0);
}
int cnt = 0;
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
if (a[i][j]) cnt++;
cout << cnt;
return 0;
}
// BFS 版本
#include <iostream>
using namespace std;
#include <cstring>
#include <queue>
const int M = 110, N = 110;
typedef pair<int, int> PII;
queue<PII> q, q_temp;
int a[N][M], re[N][M];
PII t;
int dx[] = {-1, 1, 0, 0}, dy[] = {0, 0, 1, -1}, x, y, ans, n, m;
int bfs(int ans, int time) {
for (; time > 0; time--) {
while (q.size()) {
t = q.front();
q.pop();
for (int i = 0; i < 4; i++) {
int x = t.first + dx[i], y = t.second + dy[i];
if (x > 0 && x <= n && y > 0 && y <= m && a[x][y] == 0) {
a[x][y] = 1;
ans++;
q_temp.push({x, y});
}
}
}
while (q_temp.size()) {
q.push(q_temp.front());
q_temp.pop();
}
}
return ans;
}
int main() {
cin >> n >> m;
memset(a, 0, sizeof a);
int k;
cin >> k;
ans = k;
while (k--) {
cin >> x >> y;
a[x][y] = 1;
q.push({x, y});
q_temp.push({x, y});
}
int time;
cin >> time;
cout << bfs(ans, time);
return 0;
}
第十题
问题描述 :
小蓝在一个 n 行 m 列的方格图中玩一个游戏。
开始时,小蓝站在方格图的左上角,即第 1 行第 1 列。
小蓝可以在方格图上走动,走动时,如果当前在第 r 行第 c 列,他不能走到行号比 r 小的行,也不能走到列号比 c 小的列。同时,他一步走的直线距离不超过3。
例如,如果当前小蓝在第 3 行第 5 列,他下一步可以走到第 3 行第 6 列、第 3 行第 7 列、第 3 行第 8 列、第 4 行第 5 列、第 4 行第 6 列、第 4 行第 7 列、第 5 行第 5 列、第 5 行第 6 列、第 6 行第 5 列之一。
小蓝最终要走到第 n 行第 m 列。
在图中,有的位置有奖励,走上去即可获得,有的位置有惩罚,走上去就要接受惩罚。奖励和惩罚最终抽象成一个权值,奖励为正,惩罚为负。
小蓝希望,从第 1 行第 1 列走到第 n 行第 m 列后,总的权值和最大。请问最大是多少?
输入格式
输入的第一行包含两个整数 n, m,表示图的大小。
接下来 n 行,每行 m 个整数,表示方格图中每个点的权值。
输出格式
输出一个整数,表示最大权值和。
样例输入
3 5
-4 -5 -10 -3 1
7 5 -9 3 -10
10 -2 6 -10 -4
样例输出
15
数据规模和约定
对于30%的评测用例,\(1 <= n, m <= 10\);
对于50%的评测用例,\(1 <= n, m <= 20\);
对于所有评测用例,\(1 <= n <= 100,-10000 <= 权值 <= 10000\)。
这个题目有点类似非常经典的数字三角形 ,只是可以走的路径比较多,加个判断就行
#include <iostream>
using namespace std;
using ll = long long;
const int N = 1010;
int dp[N][N], v[N][N];
int n, m;
int main() {
ios_base::sync_with_stdio(false), cin.tie(0);
cin >> n >> m;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
cin >> v[i][j];
dp[0][0] = v[0][0];
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
dp[i][j] = max(dp[i][j], max(dp[i - 1][j] + v[i][j], dp[i][j - 1] + v[i][j]));
if (i - 2 >= 0 && j - 2 >= 0)
dp[i][j] = max(dp[i][j], max(dp[i - 2][j] + v[i][j], dp[i][j - 2] + v[i][j]));
if (i - 3 >= 0 && j - 3 >= 0)
dp[i][j] = max(dp[i][j], max(dp[i - 3][j] + v[i][j], dp[i][j - 3] + v[i][j]));
}
cout << dp[n][m] + v[n][m] << endl;
return 0;
}