这周蓝桥杯举行了模拟赛,需交费,交完后大家发现上当了,没想到这难度居然是小学生水平,这明显是在……(咳嗽声),好!回归正题,今天博主给你们带来部分B组题题解,让你们重拾信心,继续进军省赛。
目录
第一题
解析:
实现:
第二题
解析:
第三题
解析:
代码:
第四题
解析:
代码:
第五题
解析:
第六题
第七题
第八题
解析:
第九题
解析:
第十题
问题描述
以下是一个 25 行 25 列的字母矩阵,全部由字母 A 和 B 组成。
AAAAAAABABBAABABABAAAAAAA
ABBBBBABBAABBBBBABABBBBBA
ABAAABABBBABAABBBBABAAABA
ABAAABABBBBBAABAABABAAABA
ABAAABABBABABBABABABAAABA
ABBBBBABBBABAABBBBABBBBBA
AAAAAAABABABABABABAAAAAAA
BBBBBBBBABAABABBBBBBBBBBB
AABAABABBAAABBAAABABBBBBA
ABBABABBBABBAAAABBBBAAAAB
BBBBAAABABAABABAABBBAABBA
BBAABABABAAAABBBAABBAAAAA
ABABBBABAABAABABABABBBBBA
AAAABBBBBABBBBAAABBBABBAB
AABAABAAABAAABAABABABAAAA
ABBBBBBBBABABBBBABAABBABA
ABBBAAABAAABBBAAAAAAABAAB
BBBBBBBBABBAAABAABBBABBAB
AAAAAAABBAAABBBBABABAABBA
ABBBBBABBAABABAAABBBABBAA
ABAAABABABBBAAAAAAAAAABAA
ABAAABABABABBBABBAABBABAA
ABAAABABBABBABABAABAABAAA
ABBBBBABABBBBBABBAAAABAAA
AAAAAAABAABBBAABABABBABBA
请问在这个矩阵中有多少个字母A?
答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
这道题不就是让我们找个数吗?我们可以用word和代码实现,当然word是非常快的,下面给你们展示一下。
word:在word文档的“开始”有个查找,点开搜索就能出这个结果
代码:
#include
using namespace std;
typedef long long LL;
string s;
int main() {
int sum=0;
for(int i=1; i<=25; i++) {
cin>>s;
for(int j=0; j
问题描述
如果一个整数的某个数位包含 2 ,则称这个数为一个“最2数字”。例如:102、2021 都是最2数字。
请问在 1(含) 到 2021(含) 中,有多少个最2数字。
答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
这是蓝桥杯的一道省赛原题,不过博主忘了是哪道了。这题很简单直接上码吧。
代码:
#include
using namespace std;
typedef long long LL;
int s;
bool judge(int n) {
while(n) {
if(n%10==2) return true;
n/=10;
}
return false;
}
int main() {
for(int i=1; i<=2021; i++)
if(judge(i)) s++;
cout<
问题描述
有一个整数 A=2021,每一次,可以将这个数加 1 、减 1 或除以 2,其中除以 2 必须在数是偶数的时候才允许。
例如,2021 经过一次操作可以变成 2020、2022。
再如,2022 经过一次操作可以变成 2021、2023 或 1011。
请问,2021 最少经过多少次操作可以变成 1。
答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
我做这题是直接手动暴搜的,2021-1=2020,2020/4=505,505-1=504,504/2=252,252/2=126,126/2=63,63+1=64,64/2=32,32/2=16,16/2=8,8/2=4,4/2=2,2/2=1,一共14步。
当然用代码实现也行,有两种方法:暴搜和BFS。
暴搜:只要是偶数就/2,只要个位是1 5 9 就-1,3 7就+1。
BFS:直接套模板吧。
暴搜:
#include
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
int main() {
int s=0;
int n=2021;
while(n!=1) {
if(n%10==1 || n%10==5 || n%10==9) {
n--;
s++;
}
if(n%10==3 || n%10==7) {
n++;
s++;
}
if(n%2==0) {
n/=2;
s++;
}
}
cout<
BFS(结构体):
#include
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
int n=2021;
int a[2050];
//结构体的朴素用法,这道题这样做是复杂化了 (调手表也能这样做,可以熟练struct和bfs配合使用)
struct node {
int x,dis;
node(int x=0, int dis=0):x(x),dis(dis) {}
};
queue q;
void bfs() {
node u(n,0);//结构体定义变量方式与int类似
q.push(u);
a[u.x]=1;//标记该值已用过
while(!q.empty()) {
node u=q.front();
q.pop();
a[u.x]=1;//标记该值已用过
if(u.x==1) {
cout<
BFS(简化):
#include
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
int n=2021;
int dis[2050];
//BFS模板(调手表那题与这题一模一样)
queue q;
void bfs() {
q.push(n);
dis[n]=1;
while(!q.empty()) {
int u=q.front();
q.pop();
if(u==1) {
cout<
问题描述
对于一个 n 行 m 列的表格,我们可以使用螺旋的方式给表格依次填上正整数,我们称填好的表格为一个螺旋矩阵。
例如,一个 4 行 5 列的螺旋矩阵如下:
1 2 3 4 5
14 15 16 17 6
13 20 19 18 7
12 11 10 9 8
请问,一个 30 行 30 列的螺旋矩阵,第 20 行第 20 列的值是多少?
答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
这题是一道典型的蛇形填数(非常熟悉好像在哪见过),看过紫书的应该都知道这道题的实现方法。一开始先往右走到头然后往下到头,再往左到头最后往上到已经走过的数的位置,然后这样绕着走,用5个while就好了。
#include
using namespace std;
typedef long long LL;
int a[35][35];
int main() {
int tot=0,x,y;
tot=a[x=1][y=1]=1;
while(tot<30*30) {
while(y+1<=30 && !a[x][y+1]) a[x][++y]=++tot;
while(x+1<=30 && !a[x+1][y]) a[++x][y]=++tot;
while(y-1>0 && !a[x][y-1]) a[x][--y]=++tot;
while(x-1>0 && !a[x-1][y]) a[--x][y]=++tot;
}
cout<
问题描述
一棵二叉树有2021个结点。该树满足任意结点的左子树结点个数和右子树的结点个数之差最多为1。
定义根结点的深度为0,子结点的深度比父结点深度多1。
请问,树中深度最大的结点的深度最大可能是多少?答案:10
答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
这题没有代码,反正可以通过手算出来就没打了(懒)。这题是二叉树,何为二叉树?一个根节点有两个子节点(可以少于2,但不能超过2),所以我们可以知道第一层是1个结点,第2层2个,第3层4个,第4层8个……以此类推。我们知道2^10=1024,而2^11=2048>2021,所以到第11层就够2021个节点了。由于根结点深度为0,所以最大的结点在第11层,即深度为10.
问题描述
一个和尚要挑水,每次最多能挑 a 千克,水缸最多能装 t 千克,开始时水缸为空。
请问这个和尚最少要挑多少次可以将水缸装满?
输入格式
输入一行包含两个整数 a, t,用一个空格分隔。
输出格式
输出一行包含一个整数,表示答案。
样例输入
20 2021
样例输出
102
评测用例规模与约定
对于所有评测用例,1 <= a <= 100,1 <= t <= 10000。
代码:
#include
using namespace std;
int main() {
int a,t;
cin>>a>>t;
if(t%a==0) cout<
问题描述
在金融领域,通常将金额的百位和千位之间、十万位和百万位之间增加逗号(千分位分隔符),以方便阅读。一般从个位开始,每三位之前增加一个逗号。
例如:1234567890.00 通常写成 1,234,567,890.00。
注意小数点后固定保留 2 位。
给定一个包含千分位分隔符的数值,请读入后输出对应的不含千分位的数值,小数点仍然保留 2 位。
输入格式
输入一行包含一个由千分位分隔符的数值,恰好有 2 位小数。
输出格式
输出不含千分位分隔符的数值,保留 2 位小数。
样例输入
1,234,567,890.00
样例输出
1234567890.00
评测用例规模与约定
对于所有评测用例,给定的数值整数部分不超过12位。
代码:
#include
using namespace std;
int main() {
string s;
cin>>s;
for(int i=0; i
问题描述
小蓝有一个插板,形状用一个 n * m 的01矩阵表示,0 表示板面,1 表示插孔。
小蓝还有一个插头,形状用一个 r * c 的01矩阵表示,0 表示没有伸出的部分,1 表示伸出的部分。插头伸出的部分必须插在插孔里面。
为了安全,插头插到面板上不能有任何部分超过插板边界(包括没有伸出的部分)。
插头和插板都不能旋转,也不能翻转。请求出插头插入插板的合理位置。
输入格式
输入的第一行包含两个整数 n, m。
接下来 n 行,每行一个长度为 m 的01串,表示插板的形状。
接下来一行包含两个整数 r, c。
接下来 r 行,每行一个长度为 c 的01串,表示插头的形状。
输出格式
如果插头没办法安全插入插板中,输出“NO”。否则输出两个数 a, b,表示插头的第 1 行第 1 列对应插板的第 a 行第 b 列。如果有多种情况满足要求,输出 a 最小的方案,如果 a 最小的方案有多个,输出在 a 最小的前提下 b 最小的方案。
样例输入
3 4
0110
0000
0000
3 3
000
010
000
样例输出
NO
样例说明
在插头不超出范围的前提下无法插入。
样例输入
4 7
1110100
1101111
0001111
0000011
2 3
111
011
样例输出
2 4
评测用例规模与约定
对于 50% 的评测用例,2 <= n, m, r, c <= 20。
对于所有评测用例,2 <= n, m, r, c <= 100。
这是一道模拟题。直接循环就好,不过需要特判一下(1个小优化):如果插头比插板大直接输出NO即可。下面就是正常的循环遍历,每一次都用插板的起点和插头的起点进行遍历对比,符合就输出,不符合就继续遍历,直到遍历到终点(插头在插板内的最后一点,往后的点都会超出插板)。如何遍历呢?循环遍历插板的点,每一次都将插板的点当作是插头的起点,然后对插头的点进行循环遍历,期间记得继续遍历插板的点(在起点上加上遍历的ij即可)。
代码:
#include
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
char a[105][105],b[105][105];
int n,m,r,c;
bool check(int x, int y) {
for(int i=0; i>n>>m;
for(int i=0; i>a[i];
//插头
cin>>r>>c;
for(int i=0; i>b[i];
//假如插板比插座小,那肯定是NO
if(r>n || r>m ||c>m || c>n) {
cout<<"NO";
return 0;
}
//开始模拟,当插座和插板同为1的时候就能进入判定了
//题目说了插头要在插板内,所以这题的模拟循环的最大值不是n,m,而是n-r,m-c(即该点是插头在插板里的最后一个遍历点,下一个点且往后的都会出插板)
for(int i=0; i<=n-r; i++)
for(int j=0; j<=m-c; j++) {
if(check(i,j)) {
cout<
问题描述
给定正整数 a, b, c,请问有多少个正整数,是其中至少两个数的约数。
输入格式
输入一行包含三个正整数 a, b, c。
输出格式
输出一行包含一个整数,表示答案。
样例输入
30 70 35
样例输出
6
样例说明
1、2、5、7、10、35满足条件。
评测用例规模与约定
对于 50% 的评测用例,1 <= a, b, c <= 1000000。
对于所有评测用例,a, b, c 不超过 10**12(10的12次方)。
这是一道数学题(小学生水平吧),题目要求至少是两个数的约数的个数,那么我们很容易想到最大公约数(gcd),可是认真想想好像和gcd没多大关系,真的吗?当然不是,我们这题依旧是得用到gcd求解,题中求的是公约数的个数,我们可以通过gcd求出最大公约数压缩范围,然后用最大公约数(max)来mod 1~max,计算出有几个公约数。
这时候有人就会问:你这不是只求了两个数的公约数吗?或者说,按你这个方法来求公约数不仅会重复求,还会超时。
莫慌,让我一一解答。这样子做当然会重复算公约数,可是我们可以用一个标记数组,当然标记数组也不可能开到10^12这么大,所以我们可以用map来判重。
对于超时的解答:n是10^12,直接for到底肯定爆,那我们就可以对齐进行开方,使其变成10^6。举一个例子,假如两个数35,70,其最大公约数是35,约数是1,5,7,35,开方后就是5。我们发现1*35=5*7=35,所以我们在循环的时候可以一次性判定两个数是否其公约数,这样就能大大节省时间了。
代码:
#include
using namespace std;
typedef long long LL;
LL a,b,c;
map M;
LL gcd(LL x,LL y) {
return y==0 ? x : gcd(y,x%y);
}
int main() {
int s=0;
cin>>a>>b>>c;
LL g=gcd(a,b);
LL h=sqrt(g);
for(int i=1; i<=h; i++) {
if(g%i==0&&!M[i]) {
s++;
M[i]=1;
}
if(g%i==0&&g/i>i && !M[g/i]) {
s++;
M[g/i]=1;
}
}
g=gcd(c,b);
h=sqrt(g);
for(int i=1; i<=h; i++) {
if(g%i==0&&!M[i]) {
s++;
M[i]=1;
}
if(g%i==0&&g/i>i && !M[g/i]) {
s++;
M[g/i]=1;
}
}
g=gcd(a,c);
h=sqrt(g);
for(int i=1; i<=h; i++) {
if(g%i==0&&!M[i]) {
s++;
M[i]=1;
}
if(g%i==0&&g/i>i && !M[g/i]) {
s++;
M[g/i]=1;
}
}
cout<
问题描述
小蓝很喜欢玩汉诺塔游戏。
游戏中有三根柱子,开始时第一根柱子上有 n 个圆盘,从上到下圆盘的大小依次为 1 到 n。
每次,可以将一个盘子从一根柱子上移动到另一根柱子上,这个盘子必须是柱子最上方的盘子,而且移到的柱子上的盘子必须比这个盘子大。
小蓝的目标是将所有的盘子移动到第三根柱子上。
汉诺塔是个经典问题,当盘子数量为 n 时,最少需要移动 2**n-1 步,其中 2**n 表示 2 的 n 次方。
小蓝已经玩了一会儿(不一定按最优方案玩),他想知道,对于他目前的局面,最少还需要多少步可以到达目标。
输入格式
输入的第一行包含三个非负整数 a, b, c,分别表示目前每根柱子上的盘子数。在本题中,n=a+b+c。
第二行包含 a 个整数,相邻的整数之间使用一个空格分隔,表示第一根柱子上的盘子,盘子按从上到下(从小到大)的顺序给出。
第三行包含 b 个整数,相邻的整数之间使用一个空格分隔,表示第二根柱子上的盘子,盘子按从上到下(从小到大)的顺序给出。
第四行包含 c 个整数,相邻的整数之间使用一个空格分隔,表示第三根柱子上的盘子,盘子按从上到下(从小到大)的顺序给出。
输出格式
输出一行包含一个整数,表示答案。
样例输入
1 2 3
1
2 3
4 5 6
样例输出
7
评测用例规模与约定
对于 30% 的评测用例,2 <= n <= 5。
对于所有评测用例,2 <= n <= 60。
博主实力有限,这题不会,抱歉!