2020第十一届蓝桥杯大赛软件类国赛题目 C/C++ B 组

试题 A: 美丽的 2

本题总分:5 分
【问题描述】
小蓝特别喜欢 2,今年是公元 2020 年,他特别高兴。
他很好奇,在公元 1 年到公元 2020 年(包含)中,有多少个年份的数位中包含数字 2?

真没想到第一题能这么简单- -
563
#include<iostream>
using namespace std;
int ans = 0;
bool judge(int n)
{
	while (n)
	{
		if (n % 10 == 2) return 1;

		n /= 10;
	}
	return 0;
}
int main()
{
	for (int i = 1; i <= 2020; i++)
	{
		if (judge(i) == 1)
		{
			ans++;
		}
	}
	cout << ans;
}

试题 B: 扩散

本题总分:5 分
【问题描述】
小蓝在一张无限大的特殊画布上作画。
这张画布可以看成一个方格图,每个格子可以用一个二维的整数坐标表示。
小蓝在画布上首先点了一下几个点:(0, 0), (2020, 11), (11, 14), (2000, 2000)。
只有这几个格子上有黑色,其它位置都是白色的。
每过一分钟,黑色就会扩散一点。具体的,如果一个格子里面是黑色,它
就会扩散到上、下、左、右四个相邻的格子中,使得这四个格子也变成黑色
(如果原来就是黑色,则还是黑色)。
请问,经过 2020 分钟后,画布上有多少个格子是黑色的

自己画了几个,发现几分钟n,某个点就会往某个方向伸n 即上下左右都是n(正上下左右)
故(0,0)上顶到2020     左2020            右边2020  下-2020
      (2020,11) 4040   -2009(差不多)  2031      0
         (11,14)  和00差距不大
   (2000,2000)4020    -20                     4040        -20
 故上下最大的差   6060
   左右最大的差     6049
   干脆把他们搞在一个6060*6060的方阵内
   这时候四个点分别转化为
  (0, 0)->  [2020][2020]
  (2020, 11)->[4040][2031]
 (11, 14)->   [2031][2034]
 (2000, 2000) ->[4020][4020]
#include<iostream>
#include<cstring>
using namespace std;
int vis[6080][6080] = { 0 };
int ans = 1;
int m[5][2] = {   
	{-1,0},
{0,-1},{0,1},
	{1,0}
};
void dfs(int x, int y, int index)
{
	if (index == 2020)
	{
		return;
	}
	//剪枝   某个点上下左右都是黑的
	if(vis[x - 1][y] == 1 && vis[x + 1][y] == 1 && vis[x][y - 1] == 1 && vis[x][y + 1] == 1) return;
	for (int i = 0; i < 4; i++)
	{
		int dx = x + m[i][0];
		int dy = y + m[i][1];
		
		if(vis[dx][dy]==0)
		{
			ans++;
			vis[dx][dy] = 1;
			dfs(dx, dy, index + 1);
			//vis[dx][dy] = 0;
		}
		else if (vis[dx][dy] == 1)
		{
			//周围全是一 这个点就不用再看了
			
				dfs(dx, dy, index + 1);	
		}
	}
	return;

}
int main()
{
	
	//memset(vis, 0, sizeof(vis));
	vis[2020][2020] = 1;
	dfs(2020, 2020, 0);
	vis[4040][2031] = 1;
	dfs(4040, 2031, 0);
	vis[2031][2034] = 1;
	dfs(2031, 2034, 0);
	vis[4020][4020] = 1;
	dfs(4020, 4020, 0);
	cout << ans;
}

试题 C: 阶乘约数

本题总分:10 分
【问题描述】
定义阶乘 n! = 1 × 2 × 3 × · · · × n。
请问 100! (100 的阶乘)有多少个约数。

试题 C: 试题 D: 本质上升序列

不会
// An highlighted block
var foo = 'bar';

试题 D: 本质上升序列

【问题描述】
小蓝特别喜欢单调递增的事物。
在一个字符串中,如果取出若干个字符,将这些字符按照在字符串中的顺序排列后是单调递增的,则成为这个字符串中的一个单调递增子序列。
例如,在字符串 lanqiao 中,如果取出字符 n 和 q,则 nq 组成一个单调递增子序列。类似的单调递增子序列还有 lnq、i、ano 等等。
小蓝发现,有些子序列虽然位置不同,但是字符序列是一样的,例如取第二个字符和最后一个字符可以取到 ao,取最后两个字符也可以取到 ao。小蓝认为他们并没有本质不同。
对于一个字符串,小蓝想知道,本质不同的递增子序列有多少个?
例如,对于字符串 lanqiao,本质不同的递增子序列有 21 个。它们分别是 l、a、n、q、i、o、ln、an、lq、aq、nq、ai、lo、ao、no、io、lnq、
anq、lno、ano、aio。
请问对于以下字符串(共 200 个小写英文字母,分四行显示):如果你把以下文字复制到文本文件中,请务必检查复制的内容是否与文档中的一致。在试题目录下有一个文件 inc.txt,内容与下面的文本相同)
tocyjkdzcieoiodfpbgcncsrjbhmugdnojjddhllnofawllbhf
iadgdcdjstemphmnjihecoapdjjrprrqnhgccevdarufmliqij
gihhfgdcmxvicfauachlifhafpdccfseflcdgjncadfclvfmad
vrnaaahahndsikzssoywakgnfjjaihtniptwoulxbaeqkqhfwl
本质不同的递增子序列有多少个?

不会
// An highlighted block
var foo = 'bar';

试题 E: 玩具蛇

【问题描述】
小蓝有一条玩具蛇,一共有 16 节,上面标着数字 1 至 16。每一节都是一
个正方形的形状。相邻的两节可以成直线或者成 90 度角。
小蓝还有一个 4×4 的方格盒子,用于存放玩具蛇,盒子的方格上依次标着
字母 A 到 P 共 16 个字母。
小蓝可以折叠自己的玩具蛇放到盒子里面。他发现,有很多种方案可以将
玩具蛇放进去。
下图给出了两种方案:
在这里插入图片描述

请帮小蓝计算一下,总共有多少种不同的方案。如果两个方案中,存在玩具蛇的某一节放在了盒子的不同格子里,则认为是不同的方案。

每个点做起点dfs遍历
答案 552
#include<iostream>
#include<cstring>
using namespace std;
int vis[5][5] = { 0 };
int ans = 0;
int m[5][2] = {
	{-1,0},
{0,-1},{0,1},
	{1,0}
};
void dfs(int x, int y, int index)
{
	if (index == 16)
	{
		ans++;
		return;
	}
	if (x < 0 || x>4 || y < 0 || y>4) return;
	for (int i = 0; i < 4; i++)
	{
		int dx = x + m[i][0];
		int dy = y + m[i][1];
		if (dx > 0 && dx < 5 && dy>0 && dy < 5)
		{
			if (vis[dx][dy] == 0)
			{
				vis[dx][dy] = 1;
				dfs(dx, dy, index + 1);
				vis[dx][dy] = 0;
			}
		}
	}
	return;

}
int main()
{
	for (int i = 1; i <= 4; i++)
	{
		for (int j = 1; j <= 4; j++)
		{
			memset(vis, 0, sizeof(vis));
			vis[i][j] = 1;
			dfs(i, j, 1);
			vis[i][j] = 0;
		}
	}
	cout << ans;
}

试题 F: 皮亚诺曲线距离

【问题描述】
皮亚诺曲线是一条平面内的曲线。
下图给出了皮亚诺曲线的 1 阶情形,它是从左下角出发,经过一个 3×3 的
方格中的每一个格子,最终到达右上角的一条曲线.
在这里插入图片描述
下图给出了皮亚诺曲线的 2 阶情形,它是经过一个 3 2 × 3 2 的方格中的每一
个格子的一条曲线。它是将 1 阶曲线的每个方格由 1 阶曲线替换而成。
在这里插入图片描述
下图给出了皮亚诺曲线的 3 阶情形,它是经过一个 3 3 × 3 3 的方格中的每一
个格子的一条曲线。它是将 2 阶曲线的每个方格由 1 阶曲线替换而成。
在这里插入图片描述
皮亚诺曲线总是从左下角开始出发,最终到达右上角。
我们将这些格子放到坐标系中,对于 k 阶皮亚诺曲线,左下角的坐标是
(0,0),右上角坐标是 (3 k − 1,3 k − 1),右下角坐标是 (3 k − 1,0),左上角坐标是
(0,3 k − 1)。
给定 k 阶皮亚诺曲线上的两个点的坐标,请问这两个点之间,如果沿着皮
亚诺曲线走,距离是到少?
【输入格式】
输入的第一行包含一个正整数 k,皮亚诺曲线的阶数。
第二行包含两个整数 x 1 , y 1 ,表示第一个点的坐标。
第三行包含两个整数 x 2 , y 2 ,表示第二个点的坐标。
【输出格式】
输出一个整数,表示给定的两个点之间的距离。
【样例输入】
1
0 0
2 2
【样例输出】
8
【样例输入】
2
0 2
0 3
【样例输出】
13
【评测用例规模与约定】
对于 30% 的评测用例,0 ≤ k ≤ 10。
对于 50% 的评测用例,0 ≤ k ≤ 20。
对于所有评测用例,0 ≤ k ≤ 100, 0 ≤ x 1 ,y 1 , x 2 ,y 2 < 3 k , x 1 ,y 1 , x 2 ,y 2 ≤ 10 18 。
数据保证答案不超过 10 18 。

不会- -
// An highlighted block
var foo = 'bar';

试题 G: 游园安排

【问题描述】
L 星球游乐园非常有趣,吸引着各个星球的游客前来游玩。小蓝是 L 星球
游乐园的管理员。
为了更好的管理游乐园,游乐园要求所有的游客提前预约,小蓝能看到系
统上所有预约游客的名字。每个游客的名字由一个大写英文字母开始,后面跟
0 个或多个小写英文字母。游客可能重名。
小蓝特别喜欢递增的事物。今天,他决定在所有预约的游客中,选择一部
分游客在上午游玩,其他的游客都在下午游玩,在上午游玩的游客要求按照预
约的顺序排列后,名字是单调递增的,即排在前面的名字严格小于排在后面的
名字。
一个名字 A 小于另一个名字 B 是指:存在一个整数 i,使得 A 的前 i 个字
母与 B 的前 i 个字母相同,且 A 的第 i+1 个字母小于 B 的第 i+1 个字母。(如
果 A 不存在第 i + 1 个字母且 B 存在第 i + 1 个字母,也视为 A 的第 i + 1 个字
母小于 B 的第 i + 1 个字母)
作为小蓝的助手,你要按照小蓝的想法安排游客,同时你又希望上午有尽
量多的游客游玩,请告诉小蓝让哪些游客上午游玩。如果方案有多种,请输出
上午游玩的第一个游客名字最小的方案。如果此时还有多种方案,请输出第一
个游客名字最小的前提下第二个游客名字最小的方案。如果仍然有多种,依此
类推选择第三个、第四个……游客名字最小的方案。
【输入格式】
输入包含一个字符串,按预约的顺序给出所有游客的名字,相邻的游客名
字之间没有字符分隔。
【输出格式】
按预约顺序输出上午游玩的游客名单,中间不加任何分隔字符。
【样例输入】
WoAiLanQiaoBei
【样例输出】
AiLanQiao
【评测用例规模与约定】
对于 20% 的评测数据,输入的总长度不超过 20 个字母。
对于 50% 的评测数据,输入的总长度不超过 300 个字母。
对于 70% 的评测数据,输入的总长度不超过 10000 个字母。
对于所有评测数据,每个名字的长度不超过 10 个字母,输入的总长度不超
过 1000000 个字母。

这个题,搞了个函数用来比大小
代码能搞一点分但是有个问题没解决:怎么确定那条路才是最长的序列 因该是bfs?这点掌握不够深没搞出来
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
#define MAX 100001
string str[MAX];
bool judge(string s1, string s2) //判断字符的大小
{
	int t = min(s1.length(), s2.length());
	for (int i = 0; i < t; i++)
	{
		if (s1[i] < s2[i]) return 1;
		if (s2[i] < s1[i]) return 0;
	}
	if (s1.length() > s2.length()) return 0;
	else return 1;

}
int main()
{
	string s;
	int i;
	string temp;
	vector<string> ans;
	//memset(str, 0, sizeof(str));
	cin >> s;
	int t = 0;
	for (int i = 0; i < s.length(); i++)
	{
		if (s[i] >= 65 && s[i] <= 90)  //
		{
			str[t].push_back(s[i]);
			i++;
			while (s[i] >= 97)  //是小数一直录用即可
			{
				str[t].push_back(s[i]);
				i++;
			}
			t++;
			i--;
			continue;
		}
	}
	if (judge(str[0], str[1]) == 0)
	{
		temp = str[1];
		ans.push_back(str[1]);
		for (int i = 2; i < t; i++)
		{
			if (judge(temp, str[i]) == 1)
			{
				temp = str[i];
				ans.push_back(str[i]);
			}
		}
	}
	else
	{
		temp = str[0];
		ans.push_back(str[0]);
		for (int i = 1; i < t; i++)
		{
			if (judge(temp, str[i]) == 1)
			{
				temp = str[i];
				ans.push_back(str[i]);
			}
		}
	}
	
	for (int i = 0; i < ans.size(); i++)
	{
		cout << ans[i];
	}

}

试题 H: 答疑

【问题描述】
有 n 位同学同时找老师答疑。每位同学都预先估计了自己答疑的时间。
老师可以安排答疑的顺序,同学们要依次进入老师办公室答疑。
一位同学答疑的过程如下:

  1. 首先进入办公室,编号为 i 的同学需要 s i 毫秒的时间。
  2. 然后同学问问题老师解答,编号为 i 的同学需要 a i 毫秒的时间。
  3. 答疑完成后,同学很高兴,会在课程群里面发一条消息,需要的时间可
    以忽略。
  4. 最后同学收拾东西离开办公室,需要 e i 毫秒的时间。一般需要 10 秒、
    20 秒或 30 秒,即 e i 取值为 10000,20000 或 30000。
    一位同学离开办公室后,紧接着下一位同学就可以进入办公室了。
    答疑从 0 时刻开始。老师想合理的安排答疑的顺序,使得同学们在课程群
    里面发消息的时刻之和最小。
    【输入格式】
    输入第一行包含一个整数 n,表示同学的数量。
    接下来 n 行,描述每位同学的时间。其中第 i 行包含三个整数 s i , a i , e i ,意
    义如上所述。
    【输出格式】
    输出一个整数,表示同学们在课程群里面发消息的时刻之和最小是多少。
    【样例输入】
    3
    10000 10000 10000
    20000 50000 20000
    30000 20000 30000
    【样例输出】
    280000
    【样例说明】
    按照 1, 3, 2 的顺序答疑,发消息的时间分别是 20000, 80000, 180000。
    【评测用例规模与约定】
    对于 30% 的评测用例,1 ≤ n ≤ 20。
    对于 60% 的评测用例,1 ≤ n ≤ 200。
    对于所有评测用例,1 ≤ n ≤ 1000,1 ≤ s i ≤ 60000,1 ≤ a i ≤ 1000000,
    e i ∈ {10000,20000,30000},即 e i 一定是 10000、20000、30000 之一。
考试时候钻牛角尖了 没搞出来 因为那时全排列用的是dfs 
后来下来了想了想还是next_函数好点
然后还涉及到了前缀和 哎这个题做了的话应该就有国奖了 没喽没喽
#include <iostream>
include<algorithm>
using namespace std;
#define MAX 1001
int a[MAX];
int ans=100000000;
struct stud {
	int a, b, c;
};
int main()
{
	int n;
	cin >> n;
	stud stu[MAX];
	for (int i = 0; i < n; i++)
	{
		cin >> stu[i].a >> stu[i].b >> stu[i].c;
		a[i] = i;
	}
	do
	{
		int temp = 0;
		int tempp = 0;
		for (int i = 0; i < n; i++)
		{
			//cout << a[i] << " ";
			if (i == 0) {
				temp += stu[a[i]].a + stu[a[i]].b;
				tempp += temp; //前缀和
			}
			else {
				temp += stu[a[i - 1]].c + stu[a[i]].a + stu[a[i]].b;
				tempp += temp;
			}	
		}
		ans = min(ans, tempp);
	} while (next_permutation(a, a + n)); //全排列
	cout << ans;
}

试题 I: 出租车

不会
题目链接

试题 J: 质数行者

不会
题目链接

  • 10
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值