第十二届蓝桥杯软件类省赛C++ B组 题目 + 题解

这篇博客详细介绍了第十二届蓝桥杯软件类C++ B组的比赛试题,包括空间、卡片、直线、货物摆放、路径、时间显示和砝码称重等问题的描述和解答思路,主要涉及算法和编程应用。
摘要由CSDN通过智能技术生成

试题 A: 空间

【问题描述】
小蓝准备用 256MB 的内存空间开一个数组,数组的每个元素都是 32 位
二进制整数,如果不考虑程序占用的空间和维护内存需要的辅助空间,请问
256MB 的空间可以存储多少个 32 位二进制整数?
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一
个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

//一位8字节
#include <iostream>
int main()
{
   
	int res = 256 * 1024 * 1024 / 4;
	cout << res << endl;
}
// 67108864

试题 B: 卡片

【问题描述】
小蓝有很多数字卡片,每张卡片上都是数字 0 到 9。
小蓝准备用这些卡片来拼一些数,他想从 1 开始拼出正整数,每拼一个,
就保存起来,卡片就不能用来拼其它数了。
小蓝想知道自己能从 1 拼到多少。
例如,当小蓝有 30 张卡片,其中 0 到 9 各 3 张,则小蓝可以拼出 1 到 10,
但是拼 11 时卡片 1 已经只有一张了,不够拼出 11。
现在小蓝手里有 0 到 9 的卡片各 2021 张,共 20210 张,请问小蓝可以从 1
拼到多少?
提示:建议使用计算机编程解决问题。
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一
个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

题解:
比赛时我是猜测1是最先用完的,然后去枚举1出现2021次。比赛时是大胆猜测,现在给出证明:
由题目知当第一次出现不够用的数字时就结束,那么肯定是数字越小越先结结束,但是又不出现000这样的数字,且每个数字出现的频率相等所以最先不够用的数字肯定是1。
这种做法并非通法,现在给出通用做法
反向思考,我们可以一直枚举,直到第一次出现某一个数不够用情况

#include <iostream>
#include <cstring>

using namespace std;
int s[10];

bool check(int x)
{
   
	while(x)
	{
   
		int t = x % 10;
		x /= 10;
		if(--s[t] < 0) return false;
	}
	return true;
}

int main()
{
   
	for(int i = 0; i < 10; i ++ ) s[i] = 2021;
	
	for(int i = 1 ;; i ++ )
	{
   
		if(!check(i))
		{
   
			cout << i - 1 << endl;
			return 0;	
		}	
	} 
	return 0;	
} 
// 3181

试题 C: 直线

【问题描述】
在平面直角坐标系中,两点可以确定一条直线。如果有多点在一条直线上,
那么这些点中任意两点确定的直线是同一条。
给定平面上 2 × 3 个整点 {(x, y)|0 ≤ x < 2, 0 ≤ y < 3, x ∈ Z, y ∈ Z},即横坐标
是 0 到 1 (包含 0 和 1) 之间的整数、纵坐标是 0 到 2 (包含 0 和 2) 之间的整数
的点。这些点一共确定了 11 条不同的直线。
给定平面上 20 × 21 个整点 {(x, y)|0 ≤ x < 20, 0 ≤ y < 21, x ∈ Z, y ∈ Z},即横
坐标是 0 到 19 (包含 0 和 19) 之间的整数、纵坐标是 0 到 20 (包含 0 和 20) 之
间的整数的点。请问这些点一共确定了多少条不同的直线。
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一
个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

题解:
比赛时想到了枚举,毕竟时间复杂度不高,202020*20 = 160000。
可是由于平时做的题还是太少,忽略了浮点数不可以用等号判相等,而且也没有考虑到斜率不存在的情况。

  • 直接枚举k,b
  • 需要注意在计算机中浮点数是不精确的,毕竟有无限不循环小数存在,所以我们再判断两个浮点数是否相等时,fabs(d1 - d2) < 1e-8这样来判断d1 ,d2是否相等
  • 最后需要注意的就是斜率不存在时有20条直线。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;
const int N = 200000;

int n;
struct Line{
   
	double k,b;
	// 重载 < 进行排序
	bool operator< (const Line& t) const
	{
   
		if(k != t.k) return k < t.k;
		return b < t.b;
	}
}l[N];

int main()
{
   
	for(int x1 = 0; x1 < 20; x1 ++ )
		for(int y1 = 0; y1 < 21; y1 ++ )
			for(int x2 = 0; x2 < 20; x2 ++ )
				for(int y2 = 0; y2 < 21; y2 ++ )
					if(x1 != x2)//如果是同一点就不进行判断
					{
   
						double k = (double)(y2 - y1) / (x2 - x1);
						double b = y1 - k * x1;
						l[n ++ ] = {
   k, b}; 
					}
	
	sort(l, l + n);
	int res = 1;
	//排序后,只需要判断相邻两个直线是否是同一条直线即可
	//考试时用到了set去做,也可以,但是得到的答案就奇奇怪怪o(╥﹏╥)o
	
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

1bu3dong

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值