2019年蓝桥杯省赛B组C++题解(无E、J题)
- 历届真题可直接在官网下载,链接:蓝桥杯大赛历届真题
A:组队
答案:500 - 10 = 490
B:年号字串
答案:2019 = 2*26^2 + 25*26 + 17 = BYQ
分析
- 没有0的26进制,转换时可依旧按照进制转换的原则
1
2
32019 % 26 = 17 --Q
(2019-17)/26 % 26 = 25 --Y
(2019-17)/26 / 26 = 2 --B
***注: 特别地按照规则: 52 % 26 = 0; 52 / 26 = 2
结果应为B0
但该进制没有0,于是前一位借1个26给后一位得AZ
提示的样例中也特意显示了52的结果为AZ
,好在问题中不涉及到0
C:数列求值
答案:4659
1 |
|
D:数的分解
答案:40785
1 |
|
F:特别数的和
——————————————完整代码————————————————
1 |
|
G:完全二叉树的权值
题目链接:·【AcWing】·完全二叉树
分析
- 完全二叉树中,通过数组[]构建树,记根节点为1,则树的第i层中第一个结点的下标为2^(i-1)
- 于是层序遍历(即遍历数组)过程中,通过层数i的累加,可记录第i层的所以结点和,存放在数组num[]中
- 题目规模N最大为10^6,
2^n - 1 < N
,可估计出数组num[]的长度n - 最后求出num[]中结点和最大的
***注:
遍历到第k个结点时,若k = 2^i
,i++
,从下一层开始重新记录结点和
——————————————完整代码————————————————
1 |
|
H:等差数列
题目链接:·【AcWing】·等差数列
分析
- 首先将n个数排序,得到缺损的等差数列,要求
最短的等差数列
,则令$a_0$、$a_{n-1}$为首、末项 - 等差数列的性质:设公差为d,任意两项的差均为d的倍数;项数 = $(a_{n-1}-a_0)/d+1$
***注:特别地,d = 0,则项数为n
- 需要d尽可能大,确定公差d有如下两种方法:
法一:枚举
算法思想
- 因为任意两项的差是d的倍数,只需数列两两做差,枚举最小的差即可
——————————————完整代码————————————————1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
/*
5
2 6 4 10 20
*/
const int maxn = 1e5+5;
const int INF = 0x3f3f3f3f;
int a[maxn];
int n;
bool judge(int minn){ //判断能否作为d
for(int i = 1; i < n; ++i){
if(a[i] % minn != 0){
return false;
}
}
return true;
}
int main(){
scanf("%d", &n);
for(int i = 0; i < n; ++i){
scanf("%d", &a[i]);
}
sort(a, a+n);
int temp = a[n-1] - a[0];
int minn = INF;
for(int i = n-1; i >=1; --i){
a[i] = a[i] - a[i-1]; //两两做差
if(a[i] < minn){
minn = a[i];
}
}
if(minn == 0){
printf("%d\n", n);
}else{
while(1){ //枚举最小的差
if(judge(minn)){
break;
}
minn--;
}
printf("%d\n", temp / minn + 1);
}
return 0;
}
法二:最大公约数
第二种方法不那么干脆,却不易想到;
算法思想
- 任意两项的差$a_j - a_i = k*d(k = 0, 1, …)$,要k尽可能大,则取所有两项差的最大公约数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22int gcd(int a, int b){ //最大公约数
return b ? gcd(b, a%b) : a;
}
int main(){
scanf("%d", &n);
for(int i = 0; i < n; ++i){
scanf("%d", &a[i]);
}
sort(a, a+n);
int temp = a[n-1] - a[0];
int minn = 0;
for(int i = n-1; i >=1; --i){
minn = gcd(minn, a[i] - a[i-1]);
}
if(minn == 0){
printf("%d\n", n);
}else{
printf("%d\n", temp / minn + 1);
}
return 0;
}
I:后缀表达式
题目链接:·【AcWing】·后缀表达式
为此专门有写一篇博客:·【蓝桥】·后缀表达式
算法思想
- M == 0
全为+号,输入的数累加即可 - M > 0
存在至少一个-运算符,后面的运算符可全变为+运算符;- 于是有了贪心的思想:
为确保结果最大,ans先加上最大的数,再减去最小的数,剩下的取绝对值,累加(即实现将运算符可全变为+)
- 于是有了贪心的思想:
——————————————完整代码————————————————
1 |
|
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!