2022蓝桥杯c++B组,解题记录
Posted NightPoetry
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2022蓝桥杯c++B组,解题记录相关的知识,希望对你有一定的参考价值。
选择题略过
本题解皆为现场题解记录,不能保证与官方题解相同。
C:刷题统计
小明决定从下周一开始努力刷题准备蓝桥杯竞赛。他计划周一至周五每天 做 a 道题目,周六和周日每天做 b 道题目。请你帮小明计算,按照计划他将在 第几天实现做题数大于等于 n 题?
当数据量较大时一天天的模拟明显速度不足,原因在于其中包含的无效计算。
如果1000天之后实现,那么是很多星期之后,而每个星期的做题量是相同的,因此这就是重复计算。所以我们采取的方法是用总题数除以每星期可以做的题目,得到需要几星期。然后余数再用模拟法判断需要几天,然后用星期*7再加上余数求出来的天数,得到总天数。
#include<iostream>
using namespace std;
int getDayNum(int tNum,int dayNum,int a,int b,int n)
for(int i=1;i<=7;i++)
if(i>=1&&i<=5)
tNum+=a;
dayNum++;
if(tNum>=n)
break;
if(i>=6)
tNum+=b;
dayNum++;
if(tNum>=n)
break;
return dayNum;
int main()
int a,b,n;
cin>>a>>b>>n;
bool flag=true;
int tNum=0;
int dayNum=0;
while(flag)
tNum+=a*5;
tNum+=b*2;
dayNum+=7;
if(tNum>=n)
flag=false;
tNum-=a*5;
tNum-=b*2;
dayNum-=7;
dayNum=getDayNum(tNum,dayNum,a,b,n);
flag=false;
cout<<dayNum;
return 0;
D:修剪灌木
爱丽丝要完成一项修剪灌木的工作。 有 N 棵灌木整齐的从左到右排成一排。爱丽丝在每天傍晚会修剪一棵灌 木,让灌木的高度变为 0 厘米。爱丽丝修剪灌木的顺序是从最左侧的灌木开始, 每天向右修剪一棵灌木。当修剪了最右侧的灌木后,她会调转方向,下一天开 始向左修剪灌木。直到修剪了最左的灌木后再次调转方向。然后如此循环往复。 灌木每天从早上到傍晚会长高 1 厘米,而其余时间不会长高。在第一天的 早晨,所有灌木的高度都是 0 厘米。爱丽丝想知道每棵灌木最高长到多高。
看到题目问最高长多高,就要去思考什么时候长到最高,而不是直接模拟。要针对问题找到方案,而不是模拟好约束条件之后暴力枚举。
在最左边的长的最高就是一个来回的时候长的最高,右边的就是从右边开始一个来回的时候长的最高,从中间分开,靠左的就是向右再回来一个来回的时候长的最高,靠右的同理,自己画图感受一下,我懒QWQ。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int main()
int n;
cin>>n;
if(n==0) cout<<0;
for(int i=1;i<=n;i++)
if(n==1)
cout<<1;
break;
int temNum=max(n-i,i-1);
cout<<temNum*2<<endl;
return 0;
E:X 进制减法
进制规定了数字在数位上逢几进一。 X 进制是一种很神奇的进制,因为其每一数位的进制并不固定!例如说某 种 X 进制数,最低数位为二进制,第二数位为十进制,第三数位为八进制,则 X 进制数 321 转换为十进制数为 65。 现在有两个 X 进制表示的整数 A 和 B,但是其具体每一数位的进制还不确 定,只知道 A 和 B 是同一进制规则,且每一数位最高为 N 进制,最低为二进 制。请你算出 A − B 的结果最小可能是多少。 请注意,你需要保证 A 和 B 在 X 进制下都是合法的,即每一数位上的数 字要小于其进制。
请参考我的b站视频:里面讲到进制的本质。蓝桥杯·寒假百校真题大联赛(大学B组)(第2期)题目讲解《年号字串》_哔哩哔哩_bilibili
简单的说进制的本质就是一个高位代表多少个低位,所以8进制10进制2进制
321
1是二进制,代表两个本位代表一个高位,所以1
2是10进制,是前一位进位来的,所以这一位的1代表一个2
3是8进制,是前一位进位来的,所以这一位1代表一个10
所以是3代表:3*10*2=60
2代表:2*2=4
1代表:1*1=1
总和:60+4+1=65
将上述过程固化为代码即可:
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
long long getNum(int *w,int *a,int ma)
long long returnNum=0;
long long nowWeiNum=1;
for(int i=0;i<ma;i++)
returnNum+=a[i]*nowWeiNum;
if(returnNum>100000000000000000) returnNum%=1000000007;
nowWeiNum*=w[i];
if(nowWeiNum>100000000000000000) break;
return returnNum;
int main()
int n,ma,mb;
cin>>n;
cin>>ma;
int a[ma];
for(int i=ma-1;i>=0;i--)
cin>>a[i];
cin>>mb;
int b[mb];
for(int i=mb-1;i>=0;i--)
cin>>b[i];
int maxLength=max(ma,mb);
int w[maxLength];
for(int i=0;i<maxLength;i++)
int numa,numb;
if(i>ma-1) numa=0;
else numa=a[i];
if(i>mb-1) numb=0;
else numb=b[i];
int wei=max(numb,numa);
wei+=1;
if(wei<2)wei=2;
w[i]=wei;
long long ansA,ansB;
ansA=getNum(w,a,ma);
ansB=getNum(w,b,mb);
cout<<(ansA-ansB)%1000000007;
return 0;
//可以用数学方法进一步的验证
因为时间不够,所以就懒得处理数据溢出问题的数学解决方法,我刷题少(个位数)考试时没想到什么方法,直接限制数据大小了。
F:统计子矩阵
给定一个 N × M 的矩阵 A,请你统计有多少个子矩阵 (最小 1 × 1,最大 N × M) 满足子矩阵中所有数的和不超过给定的整数 K
因为频繁用到矩阵的大小,所以第一个优化就是创建DP表,用差分的方式直接计算某个范围内的数的和。然后我估计着之后直接遍历所有大小的矩阵就行。
#include<iostream>
using namespace std;
int mp[1000][1000];
long long dis[1000][1000];
int main()
int ans=0;
int n,m,k;
cin>>n>>m>>k;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
cin>>mp[i][j];
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
if(i-1<0&&j-1>=0) dis[i][j]=dis[i][j-1]+mp[i][j];
else if(i-1>=0&&j-1<0) dis[i][j]=dis[i-1][j]+mp[i][j];
else if(i-1<0&&j-1<0) dis[i][j]=mp[i][j];
else dis[i][j]=dis[i-1][j]+dis[i][j-1]-dis[i-1][j-1]+mp[i][j];
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
for(int fi=0;fi<n;fi++)
for(int fj=0;fj<m;fj++)
if(i+fi>=n||j+fj>=m) continue;
long long num;
if(i-1<0&&j-1>=0)
num=dis[i+fi][j+fj]-dis[i+fi][j-1];
else if(i-1>=0&&j-1<0)
num=dis[i+fi][j+fj]-dis[i-1][j+fj];
else if(i-1<0&&j-1<0)
num=dis[i+fi][j+fj];
else
num=dis[i+fi][j+fj]-dis[i-1][j+fj]-dis[i+fi][j-1]+dis[i-1][j-1];
if(num<=k) ans++;
cout<<ans;
return 0;
G:积木画
小明最近迷上了积木画,有这么两种类型的积木,分别为 I 型(大小为 2 个单位面积)和 L 型(大小为 3 个单位面积): 同时,小明有一块面积大小为 2 × N 的画布,画布由 2 × N 个 1 × 1 区域构 成。小明需要用以上两种积木将画布拼满,他想知道总共有多少种不同的方式? 积木可以任意旋转,且画布的方向固定。
时间不做,代码我估计写起来应该涉及不少细节,所以跳过。只用排列组合计算了方形画布时的组合数。
#include<iostream>
using namespace std;
int main()
long long n;
cin>>n;
//if(n%6==0)
if(n==3) cout<<5;
else
long long block=n/6;
long long ans=1;
for(int i=1;i<=block;i++)
ans*=i;
ans*=600;
cout<<ans%1000000007;
return 0;
H:扫雷
小明最近迷上了一款名为《扫雷》的游戏。其中有一个关卡的任务如下, 在一个二维平面上放置着 n 个炸雷,第 i 个炸雷 (xi , yi ,ri) 表示在坐标 (xi , yi) 处 存在一个炸雷,它的爆炸范围是以半径为 ri 的一个圆。 为了顺利通过这片土地,需要玩家进行排雷。玩家可以发射 m 个排雷火 箭,小明已经规划好了每个排雷火箭的发射方向,第 j 个排雷火箭 (xj , yj ,rj) 表 示这个排雷火箭将会在 (xj , yj) 处爆炸,它的爆炸范围是以半径为 rj 的一个圆, 在其爆炸范围内的炸雷会被引爆。同时,当炸雷被引爆时,在其爆炸范围内的 炸雷也会被引爆。现在小明想知道他这次共引爆了几颗炸雷? 你可以把炸雷和排雷火箭都视为平面上的一个点。一个点处可以存在多个 炸雷和排雷火箭。当炸雷位于爆炸范围的边界上时也会被引爆。
遍历导弹,每有一个导弹就引爆周围的炸弹(通过对炸弹排序可以省去无效计算),炸弹爆炸放入集合,检测爆炸范围内的炸弹,如果不在集合中说明还没爆炸,加入队列。直到队列为空,计算完成这枚导弹可以炸到的全部区域。通过并查集来加速集合元素的判断。
还没测试就交卷了,为了保证一定的正确性,就不发代码了。
后面几道题没做。
以上是关于2022蓝桥杯c++B组,解题记录的主要内容,如果未能解决你的问题,请参考以下文章
2022 第十三届蓝桥杯大赛软件赛省赛,C/C++ 大学B组题解