==============================
2019-2021蓝桥杯C++ C组真题题解:
2019第十届蓝桥杯大赛软件类省赛C++ C组真题题解
2020第十一届蓝桥杯大赛软件类省赛第二场C++ C组真题题解
2021第十二届蓝桥杯大赛软件赛省赛C++ C组真题题解
==============================
题目分析:
枚举所有数,将每个数的每位取出判断即可
题目代码:
#include
using namespace std;
bool judge(int n)//判断某个数是否有2、0、1、9
{
while(n>0)
{
int tmp=n%10;
if(tmp==2||tmp==0||tmp==1||tmp==9)return true;
n=n/10;
}
return false;
}
int main()
{
int tot=0;
for(int i=1;i<=2019;i++)
{
if(judge(i))tot+=i;
}
cout<<tot<<endl;
return 0;
}
题目答案:
1905111
题目分析:
其实就是比较两个边,边相等则是正方形,边不等则大边等于大边减小边
题目代码:
#include
using namespace std;
int main()
{
int width=2019,height=324;
int tot=0;
while(width!=height)
{
if(width<height)
{
height-=width;
}else{
width-=height;
}
tot++;
}
tot++;
cout<<tot<<endl;
return 0;
}
题目答案:
21
题目分析:
这相当于就是进制问题,10进制是逢10进1,这个是逢26进1,所以这个就是26进制。我们就需要通过进制计算得出2019由26进制表达
题目代码:(注意代码得出的是反序,因为先打印的个位)
#include
using namespace std;
int main()
{
int n=2019;
while(n!=0){
int mid=n%26;//取出一位
char chr='A'+mid-1;//将其转化为字母
cout<<chr;
n=n/26;
}
return 0;
}
题目答案:
BYQ
题目分析:
枚举,直到2019个素数
题目代码:
#include
using namespace std;
int IsPrime(int n){//求解是否是素数
int i;
if(n==2)return 1;
if(n%2==0) return 0;
for(i = 3;i <= sqrt(n);i+=2){
if(n%i==0) return 0;
}
return 1;
}
int main()
{
int tot=0,i=2;
while(1)
{
if(IsPrime(i))tot++;
if(tot==2019)break;
i++;
}
cout<<i<<endl;
return 0;
}
题目答案:
17569
题目分析:
因为求降雨量最大是求七周的中位数,所以可以让前三周尽量小
这样就转换为求最后四周中最小的一周尽量大(因为它是中位数)
求最小周最大,根据经验可知,则将它们平均分即可
即1-21(不管)22-33(后四周的前三天)34-37(后四周的中位数)38-49(后四周的后三天)
题目代码:
无
题目答案:
34
题目分析:
本题输入为一行一行,输出为一列一列
使用二位数组保存数字,按照规则输出即可
题目代码:
#include
using namespace std;
int num[105][105];
int main()
{
int n,m;
cin>>n>>m;
//i表示行,j表示列
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
cin>>num[i][j];
}
}
//i表示行,j表示列
for(int j=0;j<m;j++){
for(int i=n-1;i>=0;i--){
cout<<num[i][j]<<" ";
}
cout<<endl;
}
return 0;
}
题目分析:
这道题首先要保存ts时刻,id店收到订单的信息(我使用map存入)
需要有数组保存当前时刻的优先级(更好进行处理)
需要有数组记录当前时刻每个门店是否进入优先级(因为进入和退出的标准不一样)
枚举每个时间段:
1.外卖店有订单,则优先级+3(如果外卖店已经有过订单则+2)
2.枚举每一家外卖店
将每一家外卖店优先级-1
如果优先级>5则 加入优先缓存
如果优先级<3则 退出优先缓存
如果优先级<0则 优先级为0
题目代码:
#include
using namespace std;
map<int,vector<int>> m;//每个时间段的收到订单的外卖店
int shop[100005];//保存每家店的优先级
bool shop_enter[100005];//是否进入优先缓存
int main()
{
int N,M,T,ts,id;
cin>>N>>M>>T;
for(int i=0;i<M;i++)//将每个时间段的id放入
{
cin>>ts>>id;
m[ts].push_back(id);
}
for(int j=1;j<=T;j++)//枚举每个时间段
{
sort(m[j].begin(),m[j].end());//将这个时间段的id排序
int first=-1;
for(int i=0;i<m[j].size();i++)//处理有订单的外卖店
{
if(m[j][i]!=first){//如果第一次订单
shop[m[j][i]]+=3;
}else{//如果已有订单
shop[m[j][i]]+=2;
}
first=m[j][i];
}
for(int i=1;i<=N;i++)//处理每家店
{
shop[i]--;
if(shop[i]>5)shop_enter[i]=1;
else if(shop[i]<=3)shop_enter[i]=0;
if(shop[i]<0)shop[i]=0;
}
cout<<endl;
}
int tot=0;
for(int i=1;i<=N;i++)//计算有多少家
{
if(shop_enter[i])tot++;
}
cout<<tot<<endl;
return 0;
}
题目分析:
首先将Alice和Bob的位置存入相应的容器
然后循环Alice的每一个位置,用l存放Bob的左边,用r存放Bob的右边,一直进行更新(只有这种才能保证不超时)
题目代码:
#include
using namespace std;
vector<int> Alice;
vector<int> Bob;
int main() {
int K;
string s;
cin>>K;
getchar();
getline(cin,s);//读取一行字符串
int size=s.size();
s=s+" ";//后面添加四个空格,防止溢出
char before=' ';//保证单词前面的独立
for(int i=0; i<size; i++) {
if(s[i]=='A'&&(before==' '||before=='.')) {//保证单词前面独立
if(s[i+1]=='l'&&s[i+2]=='i'&&s[i+3]=='c'&&s[i+4]=='e'&&(s[i+5]==' '||s[i+5]=='.')) {//保证单词后面独立
Alice.push_back(i+2);
}
}
if(s[i]=='B'&&(before==' '||before=='.')) {
if(s[i+1]=='o'&&s[i+2]=='b'&&(s[i+3]==' '||s[i+3]=='.')) {
Bob.push_back(i+1);
}
}
before=s[i];
}
int l=0,r=0;
long long tot=0;
for(int i=0;i<Alice.size();i++)//用l,r保证区间
{
while(l<Bob.size()&&Alice[i]-Bob[l]-4>K)
{
l++;
}
while(r<Bob.size()&&Bob[r]-Alice[i]-4<=K)
{
r++;
}
tot+=r-l;
}
cout<<tot<<endl;
return 0;
}
题目分析:
1.最大公因数,也称最大公约数、最大公因子,指两个或多个整数共有约数中最大的一个(我们可以将所有的差值进行两两最大公约数就可以找出最大的公约数)
2.因为顺序不是按从大到小,所以进行排序
3.等差数列可以为0,当差值为0时,则返回数字的个数
题目代码:
#include
using namespace std;
long long num[100005];
int difference[100005];
int main()
{
int N;
cin>>N;
for(int i=0;i<N;i++)//读取数值
{
cin>>num[i];
}
sort(num,num+N);
for(int i=1;i<N;i++)//将差值求出
{
difference[i-1]=num[i]-num[i-1];
}
int d=difference[0];
for(int i=1;i<N-1;i++)//将差值两两求最大公约数
{
d=__gcd(d,difference[i]);
}
if(d==0){
cout<<N<<endl;
}else{
cout<<(num[N-1]-num[0])/d+1<<endl;
}
return 0;
}
题目分析:
首先我们知道扫地机器人扫一边还是扫两边只要格数相同则时间一样
其实我们将扫地机器人的两边都转化为数字就可以知道
这下我们换个思路想:其实就是将这些数字每次选择一边减一,直到所有数字为0
那么我们就遍历,判断两边(如果左边数字大一点,就选择扫左边),直到所有数字都小于0
题目代码:
#include
using namespace std;
int A[100005];//存放扫地机器人的位置
int clean[100005];//存放机器人之间的位置差
int main() {
int N,K;
cin>>N>>K;
for(int i=1; i<=K; i++)cin>>A[i];
sort(A+1,A+K+1);//对机器人排序
int first=0;
for(int i=1; i<=K; i++) {//计算机器人之间的位置差
clean[i]=A[i]-first-1;
first=A[i];
}
clean[K+1]=N-first;//最后一个机器人和右边的位置差
int tot=0;
while(1) {
bool clean_up=true;
tot++;
for(int i=1; i<=K; i++) {//遍历一遍
if(clean[i]>=clean[i+1])clean[i]--;//如果左边大于等于右边
else clean[i+1]--;
if(clean[i]>0)clean_up=false;
}
if(clean[K+1]>0)clean_up=false;
if(clean_up)break;
}
cout<<tot*2<<endl;
return 0;
}