找了好久才找到第一期的题目,题目来自一位老哥文章中截图,感谢这位老哥!
第十三届蓝桥杯模拟赛(第一期)题解
因为有些题目的截图不完整,所以可能缺少输入样例和样例规模
【问题描述】
请问在 10000 (含)到 90000 (含)中,有多少个数是 128 的倍数。
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
//答案 625
#include
using namespace std;
int main() {
int ans = 0;
for (int i = 10000; i <= 90000; i++) {
if (i % 128 == 0) ans++;
}
cout << ans << endl;
return 0;
}
//答案 625
#include
using namespace std;
int main() {
int a = 10000, b = 90000;
int ans = (b - a) / 128 + (a % 128 > b % 128 || a % 128 == 0);
cout << ans << endl;
return 0;
}
【问题描述】
2021 是一个特殊的年份,它的千位和十位相同,个位比百位多一。请问从 1000 (含)到 9999 (含)有多少个这样的年份?
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
//答案 81
#include
using namespace std;
int main() {
int ans = 0;
for (int i = 1000; i <= 9999; i++) {
int a = i / 1000, b = (i / 100) % 10, c = (i / 10) % 10, d = i % 10;
if (a == c && d == b + 1) ans++;
}
cout << ans << endl;
return 0;
}
在千位确定时,十位与千位相同,个位比百位大一的可能有 9 种
从 1000 到 9999 有 9 个不同的千位
所以答案是 9 * 9 = 81
【问题描述】
如果 1 到 n 的一个排列中,所有奇数都在原来的位置上,称为一个奇不动排列。
例如,1 到 7 的排列 (1, 6, 3, 4, 5, 2, 7)是一个奇不动排列,因为1, 3, 5, 7都在原来的位置上。请问,1 到 21 的所有排列中,有多少个奇不动排列。
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
1 ~ 21 之间有 10 个偶数,奇数的位置不变,10 个偶数在 10 个位置上的全排列就是答案,即 10!
//答案 3628800
#include
using namespace std;
int main() {
int ans = 1;
for (int i = 1; i <= 10; i++){
ans *= i;
}
cout << ans << endl;
return 0;
}
【问题描述】
小蓝要上一个楼梯,共 15 级台阶。
小蓝每步可以上 1 级台阶,也可以上 2 级、3 级或 4 级,再多就没办法一步走到了。
每级台阶上有一个数值,可能正也可能负。每次走到一级台阶上,小蓝的得分就加上这级台阶上的数值。台阶上的数值依次为: 1, 2, 1, 1, 1, 1, 5, 5, 4, -1, -1, -2, -3, -1, -9。
小蓝希望不超过 6 步走到台阶顶端,请问他得分的最大值是多少?
注意,小蓝开始站在地面上,地面没有分值。他最终要走到台阶顶端,所以最终一定会走到数值为 -9 的那级台阶,所以 -9 一定会加到得分里面。
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
//答案 5
#include
using namespace std;
const int INF = 0x3f3f3f3f;
int a[16] = {0, 1, 2, 1, 1, 1, 1, 5, 5, 4, -1, -1, -2, -3, -1, -9};
int dfs(int idx, int k) {
if (idx == 15) return a[15];
if (k == 6) return -INF;
int ans = -INF;
for (int i = 1; i <= 4 && idx + i <= 15; i++) {
ans = max(ans, dfs(idx + i, k + 1));
}
return ans + a[idx];
}
int main() {
cout << dfs(0, 0) << endl;
return 0;
}
【问题描述】
在数列 a[1], a[2] … a[n] 中,如果对于下标 i, j, k 满足 0 < i < j < k < n + 1 且 a[i] < a[j] < a[k], 则称 a[i], a[j], a[k] 为一组递增三元组。
请问对于下面的长度为20的数列,有多少个递增三元组?
2, 9, 17, 4, 14, 10, 25, 26, 11, 14, 16, 17, 14, 21, 16, 27, 32, 20, 26, 36。
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
//答案 565
#include
using namespace std;
int a[20] = {2, 9, 17, 4, 14, 10, 25, 26, 11, 14, 16, 17, 14, 21, 16, 27, 32, 20, 26, 36};
int main() {
int ans = 0;
int n = 20;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
for (int k = j + 1; k < n; k++) {
if (a[i] < a[j] && a[j] < a[k]) ans++;
}
}
}
cout << ans << endl;
return 0;
}
【问题描述】
小蓝开车在高速上行驶了t 小时,速度固定为每小时 v 千米,请问小蓝在高速上行驶了多长路程?
【输入格式】
输入一行包含两个整数 t、v,用一个空格分隔。
【输出格式】
输出一行包含—个整蚁,表示答室。
【样例输入】
3 81
【样例输出】
243
【评测用例规模与约定】
对于所有评测用例, 1 <= t <= 10,1 <= v <= 150。
#include
using namespace std;
int main() {
int v, t;
cin >> t >> v;
cout << t * v << endl;
return 0;
}
【问题描述】
有一个n * m 的棋盘,现在对这个棋盘进行黑白染色,左上角染成黑色。从左上角开始,每个黑色格的相邻格染成白色,白色格的相邻格染成黑色。
以下给出了一个5 * 7的棋盘的染色示例。
(示例部分未找到 ,可以理解为已经被染色的格子不会再次被染色)
给定 n 和 m,请问棋盘上一共有多少方格被染成了黑色。
【输入格式】
输入一行包含两个整数n, m,用一个空格分隔。
【输出格式】
输出一行包含—个整数,表示答案。
【样例输入】
5 7
【样例输出】
18
【评测用例规模与约定】
对于50%的评测用例,1 <= n, m <= 10000,
对于所有评测用例,1 <= n, m <= 1000000。
对于每行的格子来说,黑色与白色是被交替染色的,若第 1 列是黑色,那么该行黑色格子数是奇数列数,否则就是偶数列数,也可知奇数行是黑色开头(行与列从 1 开始数)
可以使用一个布尔值,交替表示当前行是奇数行还是偶数行
#include
using namespace std;
typedef long long ll;
int main() {
ll m, n, ans = 0;
bool f = true;
cin >> m >> n;
if (m > n) swap(m, n); //m,n可以互换,结果不变
for (int i = 0; i < m; i++) {
ans += (n + f) / 2; //(n+1)/2表示1~n之间的奇数个数
f = !f;
}
cout << ans << endl;
return 0;
}
可以发现当行号与列号相加为偶数是,该格子是黑色,此时有两种情况:行号列号都是奇数,或者行号列号都是偶数,所以答案是:奇行个数 × 奇列个数 + 偶行个数 × 偶列个数 (行与列从 1 开始数)
#include
using namespace std;
typedef long long ll;
int main() {
ll m, n, ans = 0;
cin >> m >> n;
ans += ((m + 1) / 2) * ((n + 1) / 2);
ans += (m / 2) * (n / 2); //涉及到取整问题,括号不能少
cout << ans << endl;
return 0;
}
将棋盘每两行分为一组,容易发现每组中黑色格子占每组总格子数的一半
假设棋盘为 m 行 n 列
如果 m 为偶数,答案是所有格子数的一半,即 m * n / 2
如果 m 为奇数,答案是 (m - 1) * n / 2 + (n + 1) / 2 = (m * n + 1) / 2
又发现 m 为偶数时答案也可写成 (m * n + 1) / 2
#include
using namespace std;
int main() {
int m, n;
cin >> m >> n;
cout << (m * n + 1) / 2 << endl;
return 0;
}
【问题描述】
小蓝要在路边划分停车位。
他将路边可停车的区域划分为 L个整数小块,编号1至L。一个车位需要连续的 K 个小块,停车位不能重叠。有的小块属于井盖、消防通道等区域,不能停车。
请问小蓝最多划分出多少个停车位?
【输入格式】
输入的第一行包含三个整数 L、K、N,分别表示小块数量、一个车位需要的小块数量和不能停车的小块数量,相邻整数之间用一个空格分隔。
第二行包含 N 个整数a[1], a[2], …, a[n],按从小到大的顺序排列,相邻的整数间用空格分隔,表示这些位置不能停车。
【输出格式】
输出一行包含一个整数,表示答案。
【样例输入】
100 10 2
25 91
【样例输出】
8
【评测用例规模与约定】
该部分未找到
注意输入格式,第二行的输入会按从小到大的顺序排列
#include
using namespace std;
int main() {
int len, k, n;
cin >> len >> k >> n;
int ans = 0, last = 0, tmp;
for (int i = 0; i < n; i++) {
cin >> tmp;
ans += (tmp - last - 1) / k;
last = tmp;
}
ans += (len + 1 - last - 1) / k;
cout << ans << endl;
return 0;
}
【问题描述】
一个 1 到 n 的排列被称为人字排列,是指排列中的第 1 到第 (n + 1) / 2 个元素单调递增,第 (n + 1) / 2 到第 n 个元素单调递减。
例如: (2, 3, 5, 8, 9, 7, 6, 4, 1)是一个人字排列,而 (1, 2, 3) 和 (2, 1, 3) 都不是人字排列,(2, 4, 3) 也不是一个人字排列 (它甚至不是一个 1 到 4 的排列) 。
请问,1 到 n 的排列中有多少个人字排列?
【输入格式】
输入一行包含一个奇数 n。
【输出格式】
输出一行包含一个整数,表示答案,答案可能很大,请输出答案除以1000000007的余数。
【样例输入】
5
【样例输出】
6
【评测用例规模与约定】
该部分未找到
注意输入的 n 一定为奇数
最大的数一定固定在中间位置,再从剩下的 (n - 1) 个数中选出 (n / 2) 个数升序排列放在左边,剩下的 (n / 2) 个数降序排列放在右边,所以答案是 C(n - 1, n / 2)
#include
using namespace std;
const int MOD = 1E9 + 7;
//求从a中取b个的组合数
int getc(int a, int b) {
b = min(b, a - b);
long long ans = 1;
for (int i = 0; i < b; i++) {
ans = (ans * (a - i) / (i + 1)) % MOD;
}
return ans;
}
int main() {
int n;
cin >> n;
cout << getc(n - 1, n / 2) << endl;
return 0;
}
【问题描述】
著名设计师小蓝给蓝桥小学设计了一个教学楼。
蓝桥小学经常下雨,所以校长希望教学楼任何地方都可以连通到其它地方。
小蓝给出了教学楼的平面图,用一个 n 行 m 列的 01 矩阵表示,其中 0 表示空地,1 表示教学楼。两个相邻的 1 (上下相邻或左右相邻)之间互相可达。
请帮小蓝检查一下,是否教学楼的任意两个地方都可以连通到其它地方。
【输入格式】
输入的第一行包含两个整数 n, m,用一个空格分隔。接下来n行,每行一个长度为 m 的 01 串,表示教学楼的平面图。
【输出格式】
如果满足要求,输出“YES”,否则输出“NO”,请注意字母全部都是大写。
【样例输入】
以下部分未找到
题解中将 m 与 n 互换了,m 表示行,n 表示列
#include
using namespace std;
int m, n;
vector<string> mp;
int a[][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
bool find1(int &x, int &y) {
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (mp[i][j] == '1') {
x = i, y = j;
return true;
}
}
}
return false;
}
int main() {
cin >> m >> n;
mp.resize(m);
for (int i = 0; i < m; i++) {
cin >> mp[i];
}
int x, y;
if (!find1(x, y)) {
cout << "TES" << endl;
return 0;
}
queue<pair<int, int> > q;
mp[x][y] = '0';
q.push(make_pair(x, y));
while (!q.empty()) {
x = q.front().first;
y = q.front().second;
q.pop();
for (int i = 0; i < 4; i++) {
int xx = x + a[i][0];
int yy = y + a[i][1];
if (xx >= 0 && xx < m && yy >= 0 && yy < n && mp[xx][yy] == '1') {
mp[xx][yy] = '0';
q.push(make_pair(xx, yy));
}
}
}
if (find1(x, y)) cout << "NO" << endl;
else cout << "YES" << endl;
return 0;
}
也可用 cnt 记录矩阵中 ‘1’ 的个数,每放入队列一个坐标,就令 cnt -= 1,最后判断 cnt 是否等于 0 即可,如在方法二深搜中,每递归一次,就将 cnt -= 1
深搜有爆栈的风险,这样的题还是该广搜比较好……
#include
using namespace std;
int m, n, cnt = 0;
vector<string> mp;
int a[][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
bool find1(int &x, int &y) {
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (mp[i][j] == '1') {
if (cnt == 0) x = i, y = j;
cnt++;
}
}
}
return cnt;
}
void dfs(int x, int y) {
for (int i = 0; i < 4; i++) {
int xx = x + a[i][0];
int yy = y + a[i][1];
if (xx >= 0 && xx < m && yy >= 0 && yy < n && mp[xx][yy] == '1') {
mp[xx][yy] = '0';
cnt--;
dfs(xx, yy);
}
}
}
int main() {
cin >> m >> n;
mp.resize(m);
for (int i = 0; i < m; i++) {
cin >> mp[i];
}
queue<pair<int, int> > q;
int x, y;
if (!find1(x, y)) {
cout << "TES" << endl;
return 0;
}
cnt--;
mp[x][y] = '0';
dfs(x, y);
if (cnt) cout << "NO" << endl;
else cout << "YES" << endl;
return 0;
}