蓝桥杯专题之杂题篇

题目列表:

2013年:错误票据

2019年:完全二叉树的权值

2020年:数列求值

2020年:跑步训练,解码

2022年第二次模拟赛:哈夫曼编码

1.错误票据

题目描述

某涉密单位下发了某种票据,并要在年终全部收回。
因为工作人员疏忽,在录入ID号的时候发生了一处错误,造成了某个ID断号,另外一个ID重号。
你的任务是通过编程,找出断号的ID和重号的ID。
假设断号不可能发生在最大和最小号。
要求程序首先输入一个整数N(N<100)表示后面数据行数。
接着读入N行数据。
每行数据长度不等,是用空格分开的若干个(不大于100个)正整数(不大于100000)
每个整数代表一个ID号。
每张票据有唯一的ID号。全年所有票据的ID号是连续的,但ID的开始数码是随机选定的。
要求程序输出1行,含两个整数m n,用空格分隔。
其中,m表示断号ID,n表示重号ID
例如:
用户输入:
2
5 6 8 11 9
10 12 9

则程序输出:
7 9

再例如:
用户输入:
6
164 178 108 109 180 155 141 159 104 182 179 118 137 184 115 124 125 129 168 196
172 189 127 107 112 192 103 131 133 169 158
128 102 110 148 139 157 140 195 197
185 152 135 106 123 173 122 136 174 191 145 116 151 143 175 120 161 134 162 190
149 138 142 146 199 126 165 156 153 193 144 166 170 121 171 132 101 194 187 188
113 130 176 154 177 120 117 150 114 183 186 181 100 163 160 167 147 198 111 119
则程序输出:
105 120

代码:

#include<iostream>
#include<algorithm>
#include<sstream>
using namespace std;
int a[110];
int main(){
	int N;
	cin >> N;
	getchar();
	int k = 0,num;
	string s;
	for(int i = 0;i < N;i++){
		getline(cin,s);
		istringstream is(s);
		while(is >> num){
			a[k++] = num;
		}
	}
	sort(a,a+k);
	int d,c;
	for(int i = 0;i < k;i++){
		if(a[i] == a[i+1]){
			c = a[i];
		}
		if(a[i] + 2 == a[i+1]){//7 8 9 11    7 8 8 10
			d = a[i] + 1;
		}
	}
	cout << d << " " << c;
	return 0; 
}

2.完全二叉树的权值

【问题描述】

给定一棵包含 N 个节点的完全二叉树,树上每个节点都有一个权值,按从上到下、从左到右的顺序依次是 A1, A2, ··· AN,如下图所示:

现在小明要把相同深度的节点的权值加在一起,他想知道哪个深度的节点权值之和最大?如果有多个深度的权值和同为最大,请你输出其中最小的深度。

注:根的深度是 1。

【输入格式】

第一行包含一个整数 N。
第二行包含 N 个整数 A1, A2, ··· AN 。

【输出格式】

输出一个整数代表答案。

【样例输入】

7
1 6 5 4 3 2 1

【样例输出】

2

【评测用例规模与约定】

对于所有评测用例,1≤ N ≤100000,−100000≤ Ai ≤100000。

分析:

完全二叉树的最后一层不一定全满 

代码:

#include<iostream>
#include<cmath>
using namespace std;
const int MAX_N = 1e5+10;
const int INF = 1e7;
int N;
int a[MAX_N];
int main(){
	cin >> N;
	int k;
	int min_d = 1;
	int d = 1;
	int max_sum = -INF;
	int sum = 0;
	for(int i = 1;i <= N;i++){
		cin >> k;
		sum += k;
		if(i == pow(2,d)-1 || i == N){
			if(sum > max_sum){
				max_sum = sum;
				min_d = d;
			}
			d++;
			sum = 0;
		}
	}
	cout << min_d;
	return 0;
}

3.解码

问题描述
小明有一串很长的英文字母,可能包含大写和小写。

在这串字母中,有很多连续的是重复的。

小明想了一个办法将这串字母表达得更短:将连续的几个相同字母写成字母 + 出现次数的形式。

例如,连续的 5 个 a,即 aaaaa,小明可以简写成 a5(也可能简写成 a4a、aa3a 等)。

对于这个例子:HHHellllloo,小明可以简写成 H3el5o2。

为了方便表达,小明不会将连续的超过 9 个相同的字符写成简写的形式。

现在给出简写后的字符串,请帮助小明还原成原来的串。

输入格式
输入一行包含一个字符串。

输出格式
输出一个字符串,表示还原后的串。

样例输入
H3el5o2

样例输出
HHHellllloo

数据范围
对于所有评测用例,字符串由大小写英文字母和数字组成,长度不超过100。
请注意原来的串长度可能超过 100。

代码:

#include<iostream>
using namespace std;
int main(){
	string s;
	cin >> s;
	for(int i = 0;i < s.length();i++){
		if((s[i] >= 'a' && s[i] <= 'z') || (s[i] >= 'A' && s[i] <= 'Z')){
			cout << s[i];
		}else{
			for(int j = 0;j < s[i]-'0'-1;j++){
				cout << s[i-1];
			}
		}
	}
	return 0;
}

4.哈夫曼编码

小蓝要用01串来表达一段文字,这段文字包含 a, b, c, d, e, f 共 6 个字母,每个字母出现的次数依次为:a 出现 10 次,b 出现 20 次,c 出现 3 次,d 出现 4 次,e 出现 18 次,f 出现 50 次。
 小蓝准备分别对每个字母使用确定的01串来表示,不同字母的01串长度可以不相同。
 在表示文字时,将每个字母对应的01串直接连接起来组成最终的01串。为了能够正常还原出文字,小蓝的编码必须是前缀码,即任何一个字符对应的01串都不能是另一个字符对应的01串的前缀。
 例如,以下是一个有效的编码:
 a: 000
 b: 111
 c: 01
 d: 001
 e: 110
 f: 100
 其中 c 的长度为 2,其它字母的编码长度为 3,这种方式表示这段文字需要的总长度为:10*3+20*3+3*2+4*3+18*3+50*3=312。
 上面的编码显然不是最优的,将上面的 f 的编码改为 10,仍然满足条件,但是总长度为 262,要短 50。
 要想编码后的总长度尽量小,应当让出现次数多的字符对应的编码短,出现次数少的字符对应的编码长。
 请问,在最优情况下,编码后的总长度最少是多少?

答案:219

分析:

哈夫曼树的重要特性,就是所有叶子结点的(权重 X 路径长度)之和最小。 

先构造哈夫曼树,再根据每个节点在哈夫曼树上的位置进行计算

50+20*2+18*3+10*4+4*5+3*5 = 219

5.跑步训练

小明要做一个跑步训练。 初始时,小明充满体力,体力值计为 10000 。如果小明跑步,每分钟损耗 600 的体力。如果小明休息,每分钟增加300 的体力。体力的损耗和增加都是均匀变化的。小明打算跑一分钟、休息一分钟、再跑一分钟、再休息一分钟……如此循环。如果某个时刻小明的体力到达 0 ,他就停止锻炼。
请问小明在多久后停止锻炼。为了使答案为整数,请以秒为单位输出答案。答案中只填写数,不填写单位。

答案:3880

分析:

周不周期的容易算错,我就一分钟一分钟的算

代码:

#include<iostream>
using namespace std;
int main(){
	int x = 10000;
	int min = 0;
	while(x >= 600){
		if(min % 2 == 0){
			x-=600;
			min++;
		}
		if(min % 2 == 1){
			x+=300;
			min++;
		}
	}
	cout << min*60 + x/10;
	return 0;
}



6.数列求值

给定数列 1, 1, 1, 3, 5, 9, 17, …,从第 4 项开始,每项都是前 3 项的和。求 第 20190324 项的最后 4位数字。

答案:4659

分析:

就是一个斐波那契数列的变形。

但是我们要注意的是,你如果直接算这个值它肯定超出long long了,会溢出,只需考虑后四位对其进行mod即可求出正确答案。一般在递归或者是递推时,很容易发生爆栈,所以最好在计算每一项的时候就先取模!!!!

代码:

#include<iostream>
using namespace std;
int a[20190325];
int main(){
	a[1] = a[2] = a[3] = 1;
	for(int i = 4;i <= 20190324;i++){
		a[i] = (a[i-1]+a[i-2]+a[i-3])%1000;
	}
	cout << a[20190324];
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值