第十一届蓝桥杯第二场省赛C/C++B组题目及部分题解


真题链接:

点这里


填空题

试题A:门牌制作(5分)

问题描述:

请添加图片描述

思路简述:

简单模拟

代码:

#include<iostream>
using namespace std;
int cnt(int n){
	int ans=0;
	while(n){
		if(n%10==2)ans++;n/=10;
	}
	return ans;
}
int main(){
	int ans=0;
	for(int i=1;i<=2020;++i)
		ans+=cnt(i);
	cout<<ans<<endl;
	return 0;
}

参考结果:

624


试题B:既约分数(5分)

问题描述:

请添加图片描述

思路简述:

简单模拟

代码:

#include<iostream>
using namespace std;
int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
// 返回a和b的最大公约数
int main(){
	int n=2020,ans=0;
	for(int i=1;i<n;++i)
		for(int j=i+1;j<=n;++j)
			if(gcd(i,j)==1)ans+=2;
	cout<<ans+1<<endl;
	// 1/1也算哦 
	return 0;
}

参考结果:

2481215


试题C:蛇形填数(10分)

问题描述:

请添加图片描述

思路简述:

解法一:

第20行第20列位于斜着数第 20*2-1=39行,找到39行的首和尾两个数,进行计算742+(780-742)/2=761

代码:
#include<iostream>
using namespace std;
int main(){
	int n=39,a=0,sum=0;
	for(int i=1;i<=n;++i){
		a++;sum+=a;cout<<sum<<endl;
	}
	cout<<endl<<(sum-a+1)+a/2<<endl;
	return 0;
} 

解法二:

简单模拟。用二维vectorv来存储这斜着数39行内容。

代码:
#include<iostream>
#include<vector> 
using namespace std;
int main(){
	int n=39;
	vector<vector<int>>v(n,vector<int>(n));
	int x=0,y=0,num=0;
	for(int i=0;i<n;++i){
		for(int j=0;j<=i;++j){
			v[x][y]=++num;
			if(j==i){ //到这一斜行的右端点 
				if(i&1)++x; 
				else ++y;
			}
			else{
				if(i&1)++x,--y;
				else ++y,--x;				
			}
		}
	}
	for(int i=0;i<n;++i){
		for(int j=0;j<n-i;++j)cout<<v[i][j]<<" ";
		cout<<endl;
	}
	cout<<endl<<v[19][19]<<endl;	
	return 0;
}

参考结果:

761


试题D:跑步锻炼(10分)

问题描述:

请添加图片描述

思路简述:

模拟题。用mon存储第i月的日数。

代码:

#include<iostream>
#include<vector> 
using namespace std;
int main(){
	vector<int>mon{0,31,28,31,30,31,30,31,31,30,31,30,31};
	int y=2020,m=10,d=1;
	int ans=0,week=6;
	// week 记录今天是星期几
	for(int i=2000;i<=y;++i){ // i,j,k 枚举年月日 
		for(int j=1;j<=12;++j){
			int end=mon[j];
			if((i%400==0||i%4==0&&i%100!=0)&&j==2)end++;
            // 闰年2月29天
			for(int k=1;k<=end;++k){
				ans++;
				if(k==1||week==1)ans++;
				week=week==7?1:week+1; // 若为星期日则转为星期一
				if(i==y&&j==m&&k==d){
					cout<<ans<<endl;return 0;
				}
			}
		}
	}
	return 0;
} 

参考结果:

8879


试题E:七段码(15分)

问题描述:

请添加图片描述

思路简述:

解法一:

枚举 2n种情况。

  • 只有一管灯亮符合条件
  • x灯亮,并且与x连接的其他管不亮,不符合条件
  • 最后扣除4管灯亮,2管灯连在一块的不符合条件的情况(abde,facd,bcef)
代码:
#include<iostream>
using namespace std;
int main(){
	int ans=0; 
	for(int a=0;a<2;++a){
		for(int b=0;b<2;++b){
			for(int c=0;c<2;++c){
				for(int d=0;d<2;++d){
					for(int e=0;e<2;++e){
						for(int f=0;f<2;++f){
							for(int g=0;g<2;++g){
								int sum=a+b+c+d+e+f+g;
								if(!sum)continue;
								else if(sum==1){
									ans++;
								}
								else{
									int flag=0;
									if(a&&!b&&!f)flag=1;
									if(b&&!a&&!g&&!c)flag=1;
									if(c&&!b&&!g&&!d)flag=1;
									if(d&&!c&&!e)flag=1;
									if(e&&!d&&!f&&!g)flag=1;
									if(f&&!a&&!e&&!g)flag=1;
									if(g&&!f&&!e&&!b&&!c)flag=1;
									if(!flag)ans++;								
								}
							}
						}
					}
				}
			}
		} 
	}
	cout<<ans-3<<endl; //减去abde,facd,bcef这三种情况 
	return 0;
}

解法二:

dfs + 并查集

代码:
#include<iostream>
#include<vector>
using namespace std;
const int n=7;
vector<vector<int>>mp(n,vector<int>(n));
vector<int>v(n);
vector<int>f(n);
void un(int a,int b){
	mp[a][b]=1;mp[b][a]=1;
}
int ans=0;
int find(int a){ // 找集合的根节点 
	if(a!=f[a])f[a]=find(f[a]); 
	return f[a];
}
void dfs(int c){
	if(c==7){
		for(int i=0;i<n;++i)f[i]=i; // 初始化 
		for(int i=0;i<n;++i){ // 遍历所有可能亮灯的数码管 
			for(int j=i+1;j<n;++j){
				if(mp[i][j]&&v[i]&&v[j]){ 
				// i,j右边且i,j两管都亮 
					int a=find(i),b=find(j);
					if(a!=b)f[b]=a;	// 合并两集合 
				}
			}
		}		
		int cnt=0;
		for(int i=0;i<n;++i)
			if(v[i]&&f[i]==i)cnt++;
		if(cnt==1)ans++; // 所有亮灯都属于同一个集合 
		return;
	}
	v[c]=1; // 亮灯 
	dfs(c+1);
	v[c]=0; // 灭灯 
	dfs(c+1);}
int main(){
	// 0~6 --> a~g
	// 连接能通的边
	un(0,1);un(0,5);
	un(1,2);un(1,6);
	un(2,6);un(2,3);
	un(3,4);
	un(4,5);un(4,6);
	un(5,6);
	dfs(0);
	cout<<ans<<endl;
	return 0;
}
图解:

img

转载自 点这里

参考结果:

80



程序题

试题F:成绩统计(15分)

答题链接:

点这里

问题描述:

请添加图片描述请添加图片描述

  • 样例输入

    7
    80
    92
    56
    74
    88
    100
    0
    
  • 样例输出

    71%
    43%
    
思路简述:

简单模拟

代码:
#include<iostream> 
using namespace std;
int main(){
	int n,score,pass=0,excellent=0;cin>>n;
	for(int i=0;i<n;++i){
		cin>>score;
		if(score>=60)pass++;
		if(score>=85)excellent++;
	}
	cout<<(int)(pass*100.0/n+0.5)<<"%"<<endl;
	cout<<(int)(excellent*100.0/n+0.5)<<"%"<<endl;
	return 0;
} 

试题G:回文日期(20分)

答题链接:

点这里

问题描述:

请添加图片描述请添加图片描述

  • 样例输入

    20200202
    
  • 样例输出

    20211202
    21211212
    

思路简述:

枚举当前日期~99999999

判断当前i是否符合日期规范

若日期有效,接着判断日期是否为回文串

若为回文串,接着判断是否为ababbaba型

代码:

#include<iostream>
#include<algorithm>
#include<vector>
#include<cstdlib>
using namespace std;
vector<int>mon{0,31,28,31,30,31,30,31,31,30,31,30,31};
bool isYear(int y){ // 判断是不是闰年 
	return y%4==0&&y%100!=0||y%400==0;
}
bool judgeDate(int y,int m,int d){ // 判断该日期是否有效 
	if(m>12)return 0; // 是月份>12不正确哦 
	if(isYear(y)&&m==2)return d<=29; // 闰年的二月份 
	return d<=mon[m];
}
int main(){
	int n,f1=1,f2=1;cin>>n;
	for(int i=n+1;i<=99999999;++i){
		int y=i/10000; // 年 
		int m=i/100%100; // 月 
		int d=i%100; // 日 
		if(!judgeDate(y,m,d))continue;
		if(!f1&&!f2)break; // 都找到啦 
		string a=to_string(i); // 转成字符串 
		string b=a;
		reverse(b.begin(),b.end()); 
		if(a==b){ // 回文字符串 
			if(f1){
				cout<<i<<endl;f1=0;
			}
			// ababbaba型 
			if(a[0]==a[2]&&a[1]==a[3]&&a[1]!=a[2]&&f2){
				cout<<i<<endl;f2=0;
			}	
		}		
	}	 
	return 0;
} 

试题H:子串分值和(20分)

答题链接:

点这里

问题描述:

请添加图片描述请添加图片描述

  • 样例输入

    ababc
    
  • 样例输出

    28
    
  • 样例说明

    子串 f值
    a     1
    ab    2
    aba   2
    abab  2
    ababc 3
     b    1
     ba   2
     bab  2
     babc 3
      a   1
      ab  2
      abc 3
       b  1
       bc 2
        c 1
    
思路简述:

v来存储26个字母最后一次出现的位置

假设每个区间都是第一个出现的字母有贡献值,则贡献值为与左边相同字母的距离*右边字母个数

代码:

#include<iostream>
#include<string>
#include<vector>
using namespace std; 
typedef long long ll;
vector<int>v(26);
// 最后一次出现i+'a'的位置 
int main(){
	string s;cin>>s;
	ll ans=0;
	for(int i=0;i<26;++i)v[i]=-1; // 初始化 
	ll n=s.length();
	for(int i=0;i<n;++i){
		ans+=(i-v[s[i]-'a'])*(n-i);
		v[s[i]-'a']=i;
	}
	cout<<ans<<endl;
	return 0;
} 

试题I:平面切分(25分)

答题链接:

点这里

问题描述:

请添加图片描述请添加图片描述

  • 样例输入

    3
    1 1
    2 2
    3 3
    
  • 样例输出

    6
    

思路简述:

  • 只能过部分样例,一个小想法,但是用AcWing 提交wrong answer了

先用set去点重复的点,接着遍历每个点,计算每个点与前几个点的斜率A和截距B ,计算不重复的{A,B}对个数,当前点与前几个点将平面分为个数+1部分

代码:

#include<iostream>
#include<set> 
using namespace std;
set<pair<double,double>>p; 
//用set储存每条边(不重复) 
double a[1001],b[1001];
int main(){
	int n,ans=2,cnt=0;cin>>n;
	double x,y;
	for(int i=0;i<n;++i){
		cin>>x>>y;p.insert({x,y});
	} 
	n=p.size(); 
	set<pair<double,double>>::iterator it;
	for(it=p.begin();it!=p.end();++it)
		a[cnt]=it->first,b[cnt++]=it->second;
	for(int i=1;i<n;++i){
		set<pair<double,double>>st;
		//储存第i条线与之前的交点坐标 
		for(int j=i-1;j>=0;--j){
			if(a[i]==a[j])continue; 
			x=(b[j]-b[i])/(a[i]-a[j]); //交点的x坐标 
			y=a[i]*x+b[i]; //交点的y坐标 
			st.insert({x,y});
		}
		ans+=st.size()+1;
	}	
	cout<<ans<<endl;
	return 0; 
} 

试题J:字串排序(25分)

答题链接:

点这里

问题描述:

在这里插入图片描述在这里插入图片描述

  • 样例输入1

    4
    
  • 样例输出1

    bbaa
    
  • 样例输入2

    100
    
  • 样例输出2

    jihgfeeddccbbaa
    

思路简述:

不会哦


欢迎各位大佬在评论区发表见解哦


  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值