2020年10月蓝桥杯(软件类)省赛:题目+解答

由于今年疫情原因,原本定在4月份的省赛,被推迟到了7月和10月,分两次举行,参赛选手任意选择一场比赛即可。这次分享的是10月分举行的第二场省赛的赛题和解答。后面我会持续更新历年的真题和解答,喜欢的小伙伴可以关注我的动态哟~


系列文章:

2020年3月蓝桥杯(软件类)第一次模拟赛:题目+解答

2020年4月蓝桥杯(软件类)第二次模拟赛:题目+解答


一、填空题

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

【问题描述】
小蓝要为一条街的住户制作门牌号。
这条街一共有 2020 位住户,门牌号从 1 到 2020 编号。
小蓝制作门牌的方法是先制作 0 到 9 这几个数字字符,最后根据需要将字
符粘贴到门牌上,例如门牌 1017 需要依次粘贴字符 1、0、1、7,即需要 1 个
字符 0,2 个字符 1,1 个字符 7。
请问要制作所有的 1 到 2020 号门牌,总共需要多少个字符 2?

【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一
个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

思路
遍历+类型转换+计数

答案
624

代码

#include<iostream>
#include<sstream>
#include<algorithm>
using namespace std;

//整型转字符串 
string int_str(int n)
{
	string str;
	stringstream Convert;
	Convert<<n;
	Convert>>str;
	return str;
}

int main()
{
	int sum = 0;
	for(int i=1; i<=2020; ++i)
	{
		string str = int_str(i);
		// 查找字符串中2的个数 
		int nTwo = count(str.begin(), str.end(), '2');
		sum += nTwo;		
	}
	cout<<sum<<endl;
	
	return 0;
} 

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

【问题描述】
如果一个分数的分子和分母的最大公约数是 1,这个分数称为既约分数。
例如, 3/4 , 5/2 , 1/8 , 7/1 都是既约分数。
请问,有多少个既约分数,分子和分母都是 1 到 2020 之间的整数(包括 1
和 2020)?

【答案提交】
这是一道结果填空题,你只需要算出结果后提交即可。本题的结果为一个
整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

答案
2481215

思路
双重循环+判断

代码

#include<iostream> 
using namespace std;

int gcd(int a, int b)
{
	if (a % b == 0) return b;
	if (a > b) return gcd(a - b, b);
	else return gcd(b - a, a);
}

int main()
{
	int ans = 0;
	for (int i = 1; i <= 2020; ++i)
	{
		for (int j = 1; j <= 2020; ++j)
		{
			if (gcd(i, j) == 1) ++ans;
		}
	}
			
	cout << ans;
	
	return 0;
}

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

【问题描述】
如下图所示,小明用从 1 开始的正整数“蛇形”填充无限大的矩阵。
1 2 6 7 15 …
3 5 8 14 …
4 9 13 …
10 12 …
11 …

容易看出矩阵第二行第二列中的数是 5。请你计算矩阵中第 20 行第 20 列
的数是多少?
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一
个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

答案
761

思路
找规律:可以斜着看,第一条斜线是:1;第二条是:2, 3;第20行第20列的数在第39条斜线上的中点位置。所以该数是:1+2+…+38+20=761

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

【问题描述】
小蓝每天都锻炼身体。
正常情况下,小蓝每天跑 1 千米。如果某天是周一或者月初(1 日),为了
激励自己,小蓝要跑 2 千米。如果同时是周一或月初,小蓝也是跑 2 千米。
小蓝跑步已经坚持了很长时间,从 2000 年 1 月 1 日周六(含)到 2020 年
10 月 1 日周四(含)。请问这段时间小蓝总共跑步多少千米?

【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一
个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

答案
8879

试题E:七段码 (15分)

【问题描述】
小蓝要用七段码数码管来表示一种特殊的文字。
在这里插入图片描述
上图给出了七段码数码管的一个图示,数码管中一共有 7 段可以发光的二
极管,分别标记为 a, b, c, d, e, f, g。
小蓝要选择一部分二极管(至少要有一个)发光来表达字符。在设计字符
的表达时,要求所有发光的二极管是连成一片的。
例如:b 发光,其他二极管不发光可以用来表达一种字符。
例如:c 发光,其他二极管不发光可以用来表达一种字符。这种方案与上
一行的方案可以用来表示不同的字符,尽管看上去比较相似。
例如:a, b, c, d, e 发光,f, g 不发光可以用来表达一种字符。
例如:b, f 发光,其他二极管不发光则不能用来表达一种字符,因为发光
的二极管没有连成一片。
请问,小蓝可以用七段码数码管表达多少种不同的字符?

【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一
个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

思路
分而治之

答案
80

二、编程题

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

【问题描述】
小蓝给学生们组织了一场考试,卷面总分为 100 分,每个学生的得分都是
一个 0 到 100 的整数。
如果得分至少是 60 分,则称为及格。如果得分至少为 85 分,则称为优秀。
请计算及格率和优秀率,用百分数表示,百分号前的部分四舍五入保留整
数。

【输入格式】
输入的第一行包含一个整数 n,表示考试人数。
接下来 n 行,每行包含一个 0 至 100 的整数,表示一个学生的得分。

【输出格式】
输出两行,每行一个百分数,分别表示及格率和优秀率。百分号前的部分
四舍五入保留整数。

【样例输入】
7
80
92
56
74
88
100
0

【样例输出】
71%
43%

【评测用例规模与约定】
对于 50% 的评测用例,1 ≤ n ≤ 100。
对于所有评测用例,1 ≤ n ≤ 10000。

时间限制: 1.0s 内存限制: 256.0MB

思路
遍历+统计

代码

#include<iostream>
using namespace std;

int main()
{
	int n=0;
	cin>>n;
	int *a = new int[n];
	for(int i=0; i<n; ++i)
		cin>>a[i]; 
	int count1=0, count2=0;
	for(int i=0; i<n; ++i)
	{
		if(a[i]>=85)
			count1 += 1;
		if(a[i]>=60)
			count2 += 1;
	}
	//四舍五入 
	int rate1 = count1*100.0/n + 0.5;
	int rate2 = count2*100.0/n + 0.5;
	cout<<rate1<<"%"<<endl;
	cout<<rate2<<"%"<<endl;
	delete[] a;
	return 0;
}

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

【问题描述】
2020 年春节期间,有一个特殊的日期引起了大家的注意:2020 年 2 月 2
日。因为如果将这个日期按 “yyyymmdd” 的格式写成一个 8 位数是 20200202,
恰好是一个回文数。我们称这样的日期是回文日期。
有人表示 20200202 是 “千年一遇” 的特殊日子。对此小明很不认同,因为
不到 2 年之后就是下一个回文日期:20211202 即 2021 年 12 月 2 日。
也有人表示 20200202 并不仅仅是一个回文日期,还是一个 ABABBABA
型的回文日期。对此小明也不认同,因为大约 100 年后就能遇到下一个
ABABBABA 型的回文日期:21211212 即 2121 年 12 月 12 日。算不上 “千
年一遇”,顶多算 “千年两遇”。
给定一个 8 位数的日期,请你计算该日期之后下一个回文日期和下一个
ABABBABA 型的回文日期各是哪一天。

【输入格式】
输入包含一个八位整数 N,表示日期。

【输出格式】
输出两行,每行 1 个八位数。第一行表示下一个回文日期,第二行表示下
一个 ABABBABA 型的回文日期。

【样例输入】
20200202

【样例输出】
20211202
21211212

【评测用例规模与约定】
对于所有评测用例,10000101 ≤ N ≤ 89991231,保证 N 是一个合法日期的
8 位数表示。
时间限制: 1.0s 内存限制: 256.0MB

思路
本题的关键在于先要判断是否为合法日期。如果是合法日期,再依次判断是否为回文日期和ABABBABA 型的回文日期。

代码

#include<iostream>
#include<sstream>
#include<algorithm>
using namespace std;

string int_str(long long n)
{
	string str;
	stringstream Convert;
	Convert<<n;
	Convert>>str;
	return str;
}

bool isDate(long long n)
{
	int month = (n%10000)/100;
	int day = (n%10000)%100;
	if(month==1||month==3||month==5||month==7||month==8||month==10||month==12)
	{
		if(day<=31)
			return true;
	}
	if(month==4||month==6||month==9||month==11)
	{
		if(day<=30)
			return true;
	}
	if(month==2)
	{
		int year = n/10000;
		if((year%100!=0&&year%4==0)||(year%100==0)&&(year%400==0)) // 闰年 
		{
			if(day<=29)
				return true;
		}
		else
		{
			if(day<=28)
				return true;
		}
	}
	return false;
}

bool isHW(string str)
{
	string part1 = str.substr(0, 4); //前4位 
	string part2 = str.substr(4, 4); //后4位 
	reverse(part2.begin(), part2.end()); //反转 
	if(part1==part2) 
		return true;
	else
		return false; 
}

bool isABABBABA(string str)
{
	if(isHW(str))
	{
		if(str[0]==str[2]&&str[1]==str[3])
			return true;
	}
	return false;
}

int main()
{
	int n=0;
	cin>>n;
	
	bool flag_HW=0;//0表示输出过回文串,1表示没输出 
	for(int i=n+1; i<=89991231; ++i)
	{
		if(isDate(i))
		{
			string str = int_str(i);
			if(isHW(str)==1&&flag_HW==0)
			{
				flag_HW=1;
				cout<<i<<endl;
			}
			if(flag_HW==1&&isABABBABA(str)==1)
			{
				cout<<i<<endl;
				break;
			}
		}
	}
	
	return 0;
} 

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

【问题描述】
对于一个字符串 S,我们定义 S 的分值 f(S) 为 S 中出现的不同的字符个
数。例如 f(”aba”) = 2,f(”abc”) = 3, f(”aaa”) = 1。
现在给定一个字符串 S[0…n − 1](长度为 n),请你计算对于所有 S 的非空
子串 S[i…j](0 ≤ i ≤ j < n),f(S[i…j]) 的和是多少。

【输入格式】
输入一行包含一个由小写字母组成的字符串 S。

【输出格式】
输出一个整数表示答案。

【样例输入】
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

【评测用例规模与约定】
对于 20% 的评测用例,1 ≤ n ≤ 10;
对于 40% 的评测用例,1 ≤ n ≤ 100;
对于 50% 的评测用例,1 ≤ n ≤ 1000;
对于 60% 的评测用例,1 ≤ n ≤ 10000;
对于所有评测用例,1 ≤ n ≤ 100000。
时间限制: 1.0s 内存限制: 256.0MB

思路
先实现功能函数f(S);再遍历字符串,通过substr(start_pos, length)获取不同的子字符串。

代码

#include<iostream>
#include<algorithm>
#include<string>
using namespace std;

// f(str):str中包含不同字符的个数 
int func(string str)
{
	sort(str.begin(), str.end());
	auto iDel = unique(str.begin(), str.end());
	str.erase(iDel, str.end());
	return str.size();
}

int main()
{
	string str;
	cin>>str;
	
	long long ans = 0;
	for(int k=0; k<str.size(); ++k)
	{
		for(int i=1; i<=str.size()-k; ++i)
		{ 
			//从k位置开始,截取长度为i的子字符串 
			string sub_str = str.substr(k, i);
			ans += func(sub_str);
		}
	}
	cout<<ans<<endl;
	
	return 0;
}

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

【问题描述】
平面上有 N 条直线,其中第 i 条直线是 y = A i · x + B i 。
请计算这些直线将平面分成了几个部分。

【输入格式】
第一行包含一个整数 N。
以下 N 行,每行包含两个整数 A i , B i 。

【输出格式】
一个整数代表答案。

【样例输入】
3
1 1
2 2
3 3

【样例输出】
6
【评测用例规模与约定】
对于 50% 的评测用例,1 ≤ N ≤ 4, −10 ≤ A i , B i ≤ 10。
对于所有评测用例,1 ≤ N ≤ 1000, −100000 ≤ A i , B i ≤ 100000。

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

【问题描述】
小蓝最近学习了一些排序算法,其中冒泡排序让他印象深刻。
在冒泡排序中,每次只能交换相邻的两个元素。
小蓝发现,如果对一个字符串中的字符排序,只允许交换相邻的两个字符,
则在所有可能的排序方案中,冒泡排序的总交换次数是最少的。
例如,对于字符串 lan 排序,只需要 1 次交换。对于字符串 qiao 排序,
总共需要 4 次交换。
小蓝的幸运数字是 V,他想找到一个只包含小写英文字母的字符串,对这
个串中的字符进行冒泡排序,正好需要 V 次交换。请帮助小蓝找一个这样的字
符串。如果可能找到多个,请告诉小蓝最短的那个。如果最短的仍然有多个,
请告诉小蓝字典序最小的那个。请注意字符串中可以包含相同的字符。

【输入格式】
输入一行包含一个整数 V,为小蓝的幸运数字。

【输出格式】
输出一个字符串,为所求的答案。

【样例输入】
4

【样例输出】
bbaa

【样例输入】
100

【样例输出】

jihgfeeddccbbaa
【评测用例规模与约定】

对于 30% 的评测用例,1 ≤ V ≤ 20。
对于 50% 的评测用例,1 ≤ V ≤ 100。
对于所有评测用例,1 ≤ V ≤ 10000。
时间限制: 1.0s 内存限制: 256.0MB 本题总分:25 分

本博客会支持更新解答,你的点赞支持是我创作的最大动力!

AI 菌 CSDN认证博客专家 博客专家 CSDN合作伙伴 算法实习僧
研究僧一枚,CSDN博客专家,公众号【AI 修炼之路】作者。专注于无人驾驶(环境感知方向),热衷于分享AI、CV、DL、ML、OpenCV、Python、C++等相关技术文章。
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 猿与汪的秘密 设计师:白松林 返回首页
实付 19.90元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值