第四届传智杯刷题记录

蓝桥杯第四届真题

考前两三天才准备,因此只是简单过了一下,其中还有很多需要学习的知识点。

P8839 [传智杯 #4 初赛] 组原成绩

链接:https://www.luogu.com.cn/problem/P8839

[传智杯 #4 初赛] 组原成绩

题目描述

花栗鼠科技大学(Hualishu University of Science and Technology, HUST)的计算机组成原理快要出分了。你现在需要计算你的组原成绩如何构成。

具体来说,组原成绩分为三部分,分别是平时出勤 \(t\) ,作业 \(h\) 和考试 \(e\) 。总成绩 \(w\) 由如下公式计算:

\[w=t \times 20\% +h \times 30\%+e \times 50\% \]

其中我们保证 \(0 \leq h,e,t \leq 100\)

现在你知道了你的组原考试的 \(t,h,e\) ,你希望计算你的总成绩。

由于教务系统的特殊性,最终成绩只能是整数,采取 直接去掉小数部分 的办法。

输入格式

一行三个整数,表示 \(t,h,e\)

输出格式

一行一个整数,为 \(w\)

样例 #1

样例输入 #1
50 100 100
样例输出 #1
90

思路及代码

思路:1.注意将浮点数转为int后就是舍尾 2.不知为何scanf会报错,怀疑是vs的问题。。。换用了cincout

#include <iostream>
using namespace std;

int main() {
	float t, h, e;
	int w;
	/*scanf("%f%f%f",&t,&h,&e);*/
	cin >> t >>h >>e;
	w = t * 0.2 + h * 0.3 + e * 0.5;
	cout << w << endl;
	return 0;
}

P8840 [传智杯 #4 初赛] 报告赋分

链接:https://www.luogu.com.cn/problem/P8840

[传智杯 #4 初赛] 报告赋分

题目描述

花栗鼠科技大学的计算机组成原理实验最终的结课考核方式是提交一份报告。

然而作为任课老师,萝老师不希望大家过于内卷,所以指定了如下规定:

每份报告有一个卷面基础分 \(a\)

在此基础上:

  • 若是报告字数低于 \(16\) 页,则扣 \(10\) 分,如果分数低于 \(0\) 分了,则记作 \(0\) 分。

  • 若是报告字数超过 \(20\) 页,每超过 \(1\) 页扣 \(1\) 分 ,直到分数扣到 \(0\) 分为止。

现在你知道了一份报告的卷面基础分 \(a\) 和它的页数 \(p\) ,请你计算这份报告的最终得分。我们保证 \(1 \leq a \leq 100,1 \leq p \leq 50\).

输入格式

本题有多组数据。

第一行一个整数 \(T(1 \leq T \leq 1000)\) ,表示数据组数。

接下来 \(T\) 行,每行两个整数 \(a,p\),意义如题所示。

输出格式

\(T\) 行,每行一个整数,表示该次询问的数据最终的得分。

样例 #1

样例输入 #1

2
70 17
80 10

样例输出 #1

70
70

思路及代码

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

int main() {
	int T;
	int a, p;
	cin >> T;
	for (int i = 0; i < T; i++) {
		cin >> a >> p;
		if (p < 16) {
			int res = max(a - 10, 0);
			cout << res << endl;
		}
		else if (p > 20) {
			int res = max(0, a - (p - 20));
			cout << res << endl;
		}
		else {
			cout << a << endl;
		}
	}

	return 0;
}

P8841 [传智杯 #4 初赛] 竞争得分

链接:https://www.luogu.com.cn/problem/P8841

[传智杯 #4 初赛] 竞争得分

题目描述

为了鼓励大家写出更好的作业,花栗鼠科技大学(Hualishu University of Science and Technology, HUST)的组原实验采用了竞争得分的方式。

具体来说,假设有 \(n\) 个人提交了作业,并且其中原始得分最低的人记作 \(a_{min}\) ,原始得分最高的人记作 \(a_{max}\),第 \(i\) 个人的原始得分为 \(a_i\),那么第 \(i\) 个人的得分就是:

\[100 \times \frac{a_i-a_{min}}{a_{max}-a_{min}} \]

由于成绩系统的问题,最终录入的成绩只能是整数,采用直接去掉小数部分的方法

输入格式

第一行一个整数 \(n\) 表示人数。(\(1 \leq n \leq 1000\)

第二行共\(n\) 个整数,为序列 \(a\) ,其中 \(a_i\) 表示第 \(i\) 个人的原始作业得分。(\(1 \leq a_i \leq 1000\)

输出格式

一行,共 \(n\) 个整数,表示经过更新后每个人的得分。

样例 #1

样例输入 #1
3
1 2 3
样例输出 #1
0 50 100

思路及代码

#include <iostream>
#include <algorithm>

using namespace std;
const int N = 1000 + 5;
int main() {
	int n;
	double a[N];
	int res[N];
	double max_num = -1, min_num = 10000;
	cin >> n;
	for(int i=0;i<n;i++)
	{
		cin >> a[i];
		max_num = max(a[i], max_num);
		min_num = min(a[i], min_num);
	}
	for (int i = 0; i < n; i++) {
		res[i] = 100 * (a[i] - min_num) / (max_num - min_num);
		cout << res[i] << " ";
	}
	return 0;
}

P8843 [传智杯 #4 初赛] 萝卜数据库

链接:https://www.luogu.com.cn/problem/P8843

[传智杯 #4 初赛] 萝卜数据库

题目描述

花栗鼠很喜欢偷吃生产队的大萝卜,因此花栗鼠科技大学正在研究一种新型的数据库,叫做萝卜数据库。

具体来说,它支持 \(k(1 \leq k \leq 100)\) 个字段,每个字段名都是整数,里面存储的数值也都是整数。

现在你支持如下操作:

  • 向数据库中插入一个记录,它可能只会包含 \(k\) 个字段的某一部分。具体的操作格式详见“输入格式”。

  • 在数据库中查询有多少条符合条件的记录。

现在你总共有 \(n\) 次操作(\(1 \;\leq n \leq 1000\)),请你对每个回答操作,输出结果。

输入格式

第一行两个整数 \(n,k\) ,意义如题所述。

接下来的若干行,每行代表一次操作,具体如下:

  • \(1\ p\ x_1\ \ y_1,...,x_p\ y_p\) :表示一个插入操作,其中共有 \(p\) 个字段,第 \(i\) 字段的名字是 \(x_i\) ,值为 \(y_i\) .此处我们保证 \(1 \leq x_i \leq k, 1\leq y_i \leq 1000\),并且 \(x_i,y_i\) 均为整数。

  • \(2\ x\ y_{min}\ y_{max}\):表示一次查询操作,表示查询所有满足 字段 \(x\) 的值在 \([y_{min},y_{max}]\) 之间的记录有多少个。

输出格式

对于每个查询操作,输出一行一个整数,表示符合条件的记录个数。

样例 #1

样例输入 #1
4 5
1 2 1 2 2 4
2 2 1 5
1 2 3 5 4 6
2 4 7 8
样例输出 #1
1
0

思路及代码

思路:看起来稍微复杂了一些,但是不用任何优化,因此一个vector就解决了

#include <iostream>
#include <vector>
using namespace std;
const int N = 1000 + 5;
int main() {

	vector<int> a[N]; //下标从1开始
	int n, k;
	cin >> n >> k;
	while(n-->0) {
		int choice;
		cin >> choice;
		if (choice == 1) {
			//insert
			int p;
			cin >> p;
			while (p-->0)
			{
				int x1, y1; cin >> x1 >> y1;
				a[x1].push_back(y1);
			}
		}
		else {
			//query
			int x, y_min, y_max;
			cin >> x>>y_min>> y_max;
			int res = 0;
			for (int j = 0; j < a[x].size();j++) {
				if (a[x][j] >= y_min && a[x][j] <= y_max) {
					res++;
				}
			}
			cout << res << endl;
		}
	}
	return 0;
}

P8844 [传智杯 #4 初赛] 小卡与落叶

链接:https://www.luogu.com.cn/problem/P8844

[传智杯 #4 初赛] 小卡与落叶

题目背景

坐在飞驰的火车上,望着窗外泛黄的树叶,“又是一个冬天”,小卡心想。这是一个万物凋零的季节,一阵寒风刮过,树叶就被染黄了,再一阵寒风刮过,便是满地金黄。

百无聊赖之际,小卡发现,树叶变黄是有规律的,每一颗树,只有下面一半是黄的,上半部分都是绿的。小卡心想,该怎么统计黄色的叶子个数呢?

题目描述

给你一棵有 \(n(1\le n\le 10^5)\) 个结点的有根树,根结点标号为 \(1\),根节点的深度为 \(1\),最开始整棵树的所有结点都是绿色的。

小卡有 \(m(1\le m \le 10^5)\) 个操作。

操作一:把整棵树都染绿,之后让深度 \(\ge x\) 的结点变黄。

操作二:询问一个结点 \(x\) 的子树中有多少个黄色结点。

输入格式

第一行两个正整数 \(n,m\),表示树的结点个数和操作个数。

接下来 \(n-1\) 行,每行两个正整数 \(x,y\),表示树上的一条边。

接下来 \(m\) 行,每行两个正整数 \(op,x(1\le x\le n)\),如果 \(op=1\) 则表示操作一,否则表示操作二。

输出格式

对于每个操作二,输出一行一个正整数,表示 \(x\) 的子树中黄色结点的个数。

样例 #1

样例输入 #1
5 9
1 2
1 3
2 4
4 5
1 3
2 5
2 2
2 1
1 2
2 1
2 4
2 5
2 2
样例输出 #1
1
2
2
4
2
1
3

提示

样例一中的树如下:

第一次染色将 \(4\)\(5\) 染为黄色,查询 \(5,2,1\) 三个点的子树,答案分别为 \(1,2,2\)

第二次染色将 \(2,3,4,5\) 染为黄色,查询 \(1,4,5,2\) 四个点的子树,答案分别为 \(4,2,1,3\)

思路及代码

todo:本题属于待学习的一道题,需要用到主席树之类的知识,而且自己写的代码一方面很冗余,另一方面时间复杂度太高。

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

const int N = 100000 + 5;

class Item
{
public:
	Item();
	~Item();
	bool m_is_yellow;
	vector<int> m_sons;
	int m_son_yellow;
private:

};

Item::Item()
{
	m_son_yellow = 0;
	m_is_yellow = false;
}

Item::~Item()
{
}
//先染黄此结点,再递归染黄子节点
//返回值数目是包含本节点(如果是黄色)的
int become_yellow(int now_cen, int target_cen,int from_index, Item* a) {
	int res = 0;
	vector<int> son_vector = a[from_index].m_sons;
	if (now_cen >= target_cen) {
		if (!a[from_index].m_is_yellow) {
			a[from_index].m_is_yellow = true;
			res++;
		}
		 
	}

	for (int i = 0; i < son_vector.size(); i++) {
		int son_index = son_vector[i];
		a[son_index].m_son_yellow = become_yellow(now_cen + 1, target_cen, son_index, a);
		res += a[son_index].m_son_yellow;
	}
	return res;
}
int query(int index, Item* a) {
	int res = 0;
	if (a[index].m_is_yellow) { res++; }
	vector<int> son_vector = a[index].m_sons;
	for (int i = 0; i < son_vector.size(); i++) {
		int son_index = son_vector[i];
		res += query(son_index, a);
	}
	return res;
}
Item a[N];
int main() {
	//维护一个数组,数组里面自定义类,自定义类里面维护:当前元素,当前层数,子节点下标

	int n, m;
	int root = 1;
	cin >> n >> m;
	for (int i = 0; i < n - 1; i++) {
		int x, y;cin >> x >> y;
		a[x].m_sons.push_back(y);
	}

	//开始m次操作
	while (m-->0)
	{
		int op, x;
		cin >> op >> x;
		if (op == 1)
		{//操作1
			//全部变绿
			for (int i = 1; i <= n; i++) {
				a[i].m_is_yellow = false;
				a[i].m_son_yellow = 0;
			}
			//染黄
			a[1].m_son_yellow = become_yellow(1,x,1,a);
		}
		else {
			//操作2:查询

			/*int res = query(x, a);
			cout << res;*/
			cout<<a[x].m_son_yellow << endl;
		}
	}
	return 0;
}

P8845 [传智杯 #4 初赛] 小卡和质数

思路及代码

非常精巧的一道结论题目

怎么样的两个数异或值为 1 呢?显然是二进制下只有末尾不同的数,要满足这个条件,需要两数奇偶性不同(思考这个条件是因为考虑到质数特殊的奇偶性质),则两个质数为一奇一偶。

偶数中只有 2 是质数,而易知在其它质数中,只有 3 和 2 的异或值为 1。最终得到:两个质数只能是 3 和 2。

3 是第 22 个质数,2 是第一个质数,则 x 和 y 为 2 和 1。注意两数可能调换位置。

#include <iostream>

using namespace std;
//异或 为1,那么只能最后一位不同,说明最后一位一个是0,一个是1
//代表两个数一奇一偶,偶数质数只有2,二进制为10,与2异或为1的是3,二进制为11
int main() {
	int T;
	cin >> T;
	while (T-->0)
	{
		int x, y;
		cin >> x >> y;
		if ((x==1&&y==2)||(x==2&&y==1))
		{
			cout << "Yes" << endl;
		}
		else {
			cout << "No" << endl;
		}
	}

	return 0;
}

P8842 [传智杯 #4 初赛] 小卡与质数2

链接:https://www.luogu.com.cn/problem/P8842

思路及代码

思路在代码里,因为时间原因没有考虑到质数的范围,从而会爆TLE,但是是非常好的一道题

#include <iostream>
#include <vector>
using namespace std;
const int N = (1000000 + 5)<<1;
bool a[N]; //素数对应下标为false,这么设置反直觉,但是由于初始化全部为false,减少代码量和时间复杂度
vector<int> b;
void getPrime() {
	for (int i = 2; i <= N; i++) { //注意这里一定要从2开始,1不是素数
		if (!a[i]) {  b.push_back(i); }//没被筛掉代表这个数是素数
		for (int j = 0; j < b.size(); j++) {
			if (i*b[j] > N)
			{
				//continue; //b中存放的数越来越大,因此这里用break
				break;
			}
			a[i * b[j]] = true; //非素数,筛掉了
			if (i % b[j] == 0) { break; }
		}
	}
}
/*
有意思的思维题

乍一看不太可做,因为质数的出现没啥规律。

实际上确实是这样,我们与其枚举 yy,不如枚举更难找到规律的质数。
同时利用了一个等式:a异或b=c,那么c异或a=b,c异或b=a;因为有:a异或1 = 翻转a,a异或0=a,那么等式就好理解了
参考:https://www.luogu.com.cn/blog/20200900193lrq/solution-p8842
*/
int main() {
	//同时要考虑枚举的质数范围,即什么样的质数k才能满足:k异或x < x
	getPrime();
	//这里先不考虑质数范围,直接暴力求解一下
	int T;
	cin >> T;

	while (T-- > 0)
	{
		int x;
		cin >> x;
		int res = 0;
		for (int i = 0; i < b.size(); i++) {
			cout << b[i] << endl;
			if ((b[i] ^ x) < x)
			{
				res++;
			}
		}
		//cout << res << endl;
	}
	return 0;
}

posted @ 2022-11-25 15:34  思wu邪  阅读(114)  评论(0编辑  收藏  举报