当前位置: 首页 > news >正文

蓝桥杯十一届C++B组真题题解

试题A :门牌制作


【问题描述】

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

【答案提交】

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

#include <iostream>
using namespace std;

int main()
{
	int count = 0;
	for (int i = 1; i <= 2020;i++)
	{
		int x = i;
		while (x)
		{
			if (x % 10 == 2) count++;
			x /= 10;
		}
	}
	cout << count;
	return 0;
}

无需多言,直接暴力枚举

答案:624

试题B :既约分数


【问题描述】

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

【答案提交】

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

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

int gcd(int a, int b) {
	int r;
	while (a % b != 0) {
		r = a % b;
		a = b;
		b = r;
	}
	return b;
}

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

直接使用最大公约数函数,遍历元素即可

试题C :蛇形填数


【问题描述】

如下图所示,小明用从1 开始的正整数“蛇形”填充无限大的矩阵。
容易看出矩阵第二行第二列中的数是5。请你计算矩阵中第20 行第20 列的数是多少?

【答案提交】

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

#include <iostream>
#include<vector>
using namespace std;

int vv[999][999];
int main()
{
	int count = 2;
	int flag = 1;
	for (int i = 2; i <= 50; i++)
	{
		int x = i;
		if (flag == 1)//从上到下
		{
			int y = 1;
			while (x > 0)
			{
				vv[y++][x--] = count++;
			}
			flag *= -1;
		}
		else if (flag == -1)
		{
			int y = 1;
			while (x > 0)
			{
				vv[x--][y++] = count++;
			}
			flag *= -1;
		}
	}
	cout << vv[20][20];
	return 0;
}

这道题的矩阵是斜着填充的,我们只需要根据顺序来填充矩阵即可

试题D :跑步训练


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

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

#include <iostream>
using namespace std;

int monthday[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };

int aaa(int year)
{
	if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
	{
		return 1;
	}
	else return 0;
}

int main()
{
	int year = 2020, month = 1, day = 1;
	int w = 6;
	int count = 0;
	int x = 12, y = 0;
	for (int i = 2000; i <= 2020; i++)
	{
		if (i == 2020) x = 10;
		for (int j = 1; j <= x; j++)
		{
			if (j == 2)
			{
				if (aaa(i)) monthday[2] = 29;
				else monthday[2] = 28;
			}

			if (i == 2020 && j == 10) monthday[10] = 1;

			for (int k = 1; k <= monthday[j]; k++)
			{
				if (w == 1 || k == 1) count += 2;
				else count += 1;

				if (w < 7) w++;
				else w = 1;
			}
		}
	}
	cout << count;
	return 0;
}

这是一道比较基础的日期类问题,只需要判断闰年,日期,以及结束条件即可解决

答案:8879

试题E :七段码


【问题描述】
小蓝要用七段码数码管来表示一种特殊的文字。


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

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

#include <iostream>
using namespace std;

int con[8][8], vis[8], a[8];
int res = 0;

int find(int n) {
	if (a[n] == n) return n;
	a[n] = find(a[n]); 
	return a[n];
}

void dfs(int i)
{
	if (i > 7)
	{
		for (int i = 1; i <= 7; i++) a[i] = i;
		for (int i = 1; i <= 7; i++)
		{
			for (int j = 1; j <= 7; j++)
			{
				if (vis[i] && vis[j] && con[i][j])
				{
					int x = find(i), y = find(j);
					if (x != y)
					{
						a[x] = y;
					}
				}
			}
		}
		int k = 0;
		for (int i = 1; i <= 7; i++)
		{
			if (vis[i] && a[i] == i) k++;
		}
		if (k == 1) res++;
		return;
	}
	vis[i] = 1;
	dfs(i + 1);
	vis[i] = 0;
	dfs(i + 1);
}

int main()
{
	con[1][2] = con[1][6] = 1;
	con[2][1] = con[2][7] = con[2][3] = 1;
	con[3][7] = con[3][4] = con[3][2] = 1;
	con[4][5] = con[4][3] = 1;
	con[5][4] = con[5][7] = con[5][6] = 1;
	con[6][1] = con[6][7] = con[6][5] = 1;
	con[7][6] = con[7][5] = con[7][2] = con[7][3] = 1;
	dfs(1);
	cout << res;
    return 0;
}

这道题目考验的是dfs和并查集功能,需要查找联通的部分是否属于一个集合

首先我们需要将每个位置的邻居置为1,以便在dfs中判断,当排列的灯管数量超过7个之后,我们需要进行判断

if (vis[i] && vis[j] && con[i][j]):

当且仅当段 i 和段 j 同时被选中(vis[i] && vis[j])且两者相邻(con[i][j])时,才需要将它们的集合合并。这是为了确保:

  1. 只有被选中的段参与连通性检查:未选中的段不影响最终结果。

  2. 相邻段的连通性被正确合并:如果两个段相邻且都被选中,它们的连通性需要通过并查集合并

if (vis[i] && a[i] == i):

遍历所有段,统计满足以下条件的段数量:

  1. 段 i 被选中:仅处理选中的段。

  2. 段 i 是所在集合的根节点:根节点数量代表连通分量的数量。

最终判断
如果所有选中的段属于同一个连通分量,则根节点数量 k 为 1,此时组合合法(sum++)。

试题F:成绩统计

题目描述

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

输入格式

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

输出格式

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

样例输入

7
80
92
56
74
88
100
0

样例输出

71%
43%
#include <iostream>
#include<vector>
#include<algorithm>
#include<string>
#include <unordered_set>
#include<cmath>
using namespace std;

int main()
{
    int n = 0;
    cin >> n;
    vector<int> v(n);
    int a = 0, b = 0;
    for (int i = 0; i < n; i++)
    {
        cin >> v[i];
        if (v[i] >= 60) a++;
        if (v[i] >= 85) b++;
    }

    double aa = static_cast<double>(a) / n;
    double bb = static_cast<double>(b) / n;
    aa *= 100;
    bb *= 100;
    cout << round(aa) << '%'<<endl;
    cout << round(bb) << '%';
    return 0;
}

直接使用C++库函数进行四舍五入即可

试题G:回文日期

题目描述

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
#include <iostream>
#include<vector>
#include<algorithm>
#include<string>
#include <unordered_set>
#include<cmath>
using namespace std;

int monthday[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };

bool aaa(int year)
{
	if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
		return true;
	else {
		return false;
	}
}

bool isAB(string s)//ABABBABA
{
	if (s[0] == s[2] && s[2] == s[5] && s[5] == s[7] &&
		s[1] == s[3] && s[3] == s[4] && s[4] == s[6] &&
		s[0] != s[1]) {
		return true;
	}
	return false;
}

void nextday(int& year, int& month, int& day)
{
	if (month == 2 && aaa(year)) monthday[2] = 29;
	else monthday[2] = 28;

	if (day < monthday[month]) day++;
	else
	{
		if (month == 12)
		{
			year++;
			month=1;
		}
		else month++;

		day=1;
	}
}
int main()
{
	string s;
	cin >> s;//转换成整数
	int flag1 = 0, flag2 = 0;//1判断AB型,2判断回文
	string ss1, ss2;
	int year = stoi(s.substr(0, 4));
	int month = stoi(s.substr(4, 2));
	int day = stoi(s.substr(6, 2));

	while (flag1 == 0 || flag2 == 0)
	{
		nextday(year, month, day);
		string s1;
		s1.push_back((year/1000)+'0');
		s1.push_back((year/100%10) + '0');
		s1.push_back((year/10%10) + '0');
		s1.push_back((year%10) + '0');
		s1.push_back((month/10) + '0');
		s1.push_back((month%10) + '0');
		s1.push_back((day/10) + '0');
		s1.push_back((day%10) + '0');
		if (flag2 == 0)
		{
			int flag = 0;
			for (int i = 0, j = 7; i < j; i++, j--)
			{
				if (s1[i] != s1[j])
				{
					flag = -1;
					break;
				}
			}
			if (flag == 0)
			{
				ss2 = s1;
				flag2 = 1;
			}
		}
		if (flag1 == 0)
		{
			if (isAB(s1))
			{
				ss1 = s1;
				flag1 = 1;
			}
		}
	}

	cout << ss2 << endl;
	cout << ss1 << endl;
    return 0;
}

这道题目主要考察日期类以及字符串的相关知识,代码量比较多,但是难度不大
 

试题H:子串分值

题目描述

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

输入格式

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

输出格式

输出一个整数表示答案。

样例输入

ababc

样例输出

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

int main() {
    string s;
    cin >> s;
    int n = s.size();
    long long total = (long long)n * (n + 1) / 2;
    long long ans = 0;

    for (char c = 'a'; c <= 'z'; ++c) {
        long long sum_not = 0;
        int current = 0;
        for (int i = 0; i < n; ++i) {
            if (s[i] != c) {
                current++;
            } else {
                sum_not += (long long)current * (current + 1) / 2;
                current = 0;
            }
        }
        sum_not += (long long)current * (current + 1) / 2;
        ans += (total - sum_not);
    }

    cout << ans << endl;
    return 0;
}

这道题目如果使用暴力枚举的话并不能拿到全部分数,需要用到一些数学技巧

一个长度为n的字符串所有的子串数量为n*(n+1)/2 ,我们需要用到这个技巧

接着开始遍历26个字母,然后在循环中遍历字符串,找出不包含字符c的子串数量

current用于统计子串长度,sum_not用于统计不包含当前字符c的子串数量

total - sum_not是包含当前字符 c 的子字符串数量。

示例:

假设输入字符串是 "abc",以下是计算过程:

  1. 总子字符串数量

    total=6

    子字符串包括:"a", "ab", "abc", "b", "bc", "c"

  2. 遍历字符 'a'

    • 不包含 'a' 的子字符串是 "b", "bc", "c",数量为 3。

    • 包含 'a' 的子字符串数量为 6−3=3。

  3. 遍历字符 'b'

    • 不包含 'b' 的子字符串是 "a", "ab", "abc", "c",数量为 4。

    • 包含 'b' 的子字符串数量为 6−4=2。

  4. 遍历字符 'c'

    • 不包含 'c' 的子字符串是 "a", "ab", "b",数量为 3。

    • 包含 'c' 的子字符串数量为 6−3=3。

  5. 其他字符(如 'd' 到 'z')

    • 这些字符在字符串中不存在,所以它们的 sum_not 是 6,包含它们的子字符串数量是 0。

累加起来即可得出答案

试题I:平面切分

题目描述

平面上有N条直线,其中第 i 条直线是y=Ai⋅x+Bi。请计算这些直线将平面分成了几个部分。

输入格式

第一行包含一个整数 N。以下N行,每行包含两个整数 Ai,Bi。

输出格式

一个整数代表答案。

样例输入

3
1 1
2 2
3 3

样例输出

6
#include <iostream>
#include<vector>
#include<algorithm>
#include<string>
#include <unordered_set>
#include<cmath>
#include <set>
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<double, double> pdd;
set<pii> s;
ll ans = 1;

int point(int x, int y)
{
    set<pdd> s1;
    for (auto it = s.begin(); it != s.end(); it++)
    {
        double x1 = 1.0 * (*it).first, y1 = 1.0 * (*it).second;
        if (x != x1)
        {
            double x2 = 1.0 * (y-y1) / (x - x1);
            double y2 = x * x2 + y;
            s1.insert({ x2,y2 });
        }
    }
    return s1.size();
}

int main()
{
    int n;
    cin >> n;
    for (int i = 0; i < n; i++)
    {
        int x, y;
        cin >> x >> y;
        int size = s.size();
        s.insert({ x,y });
        if (size != s.size())
        {
            ans += point(x, y) + 1;
        }
    }
    cout << ans << endl;
    return 0;
}

这道题目考察到的知识点是数学素养,判断切割平面有三种情况

1.线重合  2.点重合 3.线平行

线重合:A和B都相等,平面个数不变

线平行:平面数量+1

点重合:平面数量加上点重合个数再加上1.

试题J 字串排序


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

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

【输出格式】
题面要求的一行字符串。

【样例输入】
4
【样例输出】
bbaa
【样例输入】
100
【样例输出】
jihgfeeddccbbaa

这道题难度较大,给大家推荐1篇博客

冒泡排序与字符交换构建特定逆序数字符串-CSDN博客

http://www.dtcms.com/a/122967.html

相关文章:

  • 革新电销流程,数企云外呼开启便捷 “直通车”
  • 各种场景的ARP攻击描述笔记(超详细)
  • stream流Collectors.toMap(),key值重复问题
  • Bootstrap Table动态修改列标题
  • C++中命名空间namespace|头文件h文件|源文件cpp文件详解
  • pyecharts常用图形
  • Mysql索引(二)
  • 8.第二阶段x64游戏实战-string类
  • UE学习记录part15
  • ffpyplayer+Qt,制作一个视频播放器
  • 玩转Docker | 使用Docker安装FileDrop文件共享工具
  • 如何解【决泛型作为运行时参数】时类型擦除问题
  • PowerBI数据建模2:计算选项、计算组
  • JavaScript实用API
  • 计算机视觉4——特征点及其描述子
  • LeetCode344反转字符串
  • 亮相2025全球分布式云大会,火山引擎边缘云落地AI新场景
  • 1. 两数之和 leetcode
  • 后缀自动机SAM练习笔记 (一)
  • Pandas-按索引从df中读取指定一个或者多个元素
  • Pytorch Dataset问题解决:数据集读取报错DatasetGenerationError或OSError
  • win10离线环境下配置wsl2和vscode远程开发环境
  • spark-Core
  • 基于vue3与supabase系统认证机制
  • 大模型分布式推理和量化部署
  • 高可用之战:Redis Sentinal(哨兵模式)
  • Docker基础2
  • 【教程】Windows 电脑部署使用 config2spec 详细教程
  • 基于ueditor编辑器的功能开发之给编辑器图片增加水印功能
  • 智能防灾网:气象灾害风险管理系统的科技力量与未来蓝图