蓝桥杯 2020年省赛真题 (C/C++ 大学A组 )
??打发时间。
#A 跑步训练
本题总分:
5
5
5 分
问题描述
??小明要做一个跑步训练。 ??初始时,小明充满体力,体力值计为
10000
10000
10000。如果小明跑步,每分钟损耗
600
600
600 的体力。如果小明休息,每分钟增加
300
300
300 的体力。体力的损耗和增加都是均匀变化的。 ??小明打算跑一分钟、休息一分钟、再跑一分钟、再休息一分钟 …… 如此循环。如果某个时刻小明的体力到达
0
0
0,他就停止锻炼。 ??请问小明在多久后停止锻炼。为了使答案为整数,请以秒为单位输出答案。答案中只填写数,不填写单位。
答案提交
??这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
3880
#include <stdio.h>
int N = 10000, k = 5, ans = 0, K[2]{ 1, -1};
int main() {
for (int opt = 1; N > 0; opt ^= 1)
for (int i = 0; i < 60 && N > 0; i++)
N += K[opt] * (opt + 1) * k, ++ans;
if (N < 0) --ans;
printf("%d", ans);
}
??简单的模拟题。
#B 合并检测
本题总分:
5
5
5 分
问题描述
??新冠疫情由新冠病毒引起,最近在
A
\mathrm A
A 国蔓延,为了尽快控制疫情,
A
\mathrm A
A 国准备给大量民众进病毒核酸检测。 ??然而,用于检测的试剂盒紧缺。 ??为了解决这一困难,科学家想了一个办法:合并检测。即将从多个人(
k
k
k 个)采集的标本放到同一个试剂盒中进行检测。如果结果为阴性,则说明这
k
k
k 个人都是阴性,用一个试剂盒完成了
k
k
k 个人的检测。如果结果为阳性,则说明至少有一个人为阳性,需要将这
k
k
k 个人的样本全部重新独立检测(从理论上看,如果检测前
k
?
1
k ? 1
k?1 个人都是阴性可以推断出第
k
k
k 个人是阳性,但是在实际操作中不会利用此推断,而是将
k
k
k 个人独立检测),加上最开始的合并检测,一共使用了
k
+
1
k + 1
k+1 个试剂盒完成了
k
k
k 个人的检测。 ??
A
\mathrm A
A 国估计被测的民众的感染率大概是
1
1
1%,呈均匀分布。请问
k
k
k 取多少能最节省试剂盒?
答案提交
??这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
10
朴素解法
#include <stdio.h>
int N = 10000, ans = 100;
int calc(int k) { return N / k + N / 100 * k; }
int main() {
for (int i = 1; i < 100; ++i)
if (calc(i) < calc(ans)) ans = i;
printf("%d", ans);
}
??设
N
N
N 为民众人数,然后暴力枚举
[
1
,
100
)
[1,100)
[1,100) 这个区间就行,因为
k
≥
100
k \geq 100
k≥100 时,每个人都要重新做一遍检测,答案必不优。
数理分析
??感染人数呈均匀分布,即
p
{
θ
=
某
民
感
染
}
=
1
100
p\{\theta = 某民感染\} = \frac 1{100}
p{θ=某民感染}=1001?、
p
{
θ
=
某
民
健
康
}
=
99
100
p\{\theta = 某民健康\} = \frac {99}{100}
p{θ=某民健康}=10099?,
??
k
k
k 名群众中无有感染者,可以看作为
k
k
k 重伯努利试验,其中有感染者的概率为
∑
i
=
1
k
(
C
k
i
(
1
100
)
i
(
99
100
)
k
?
i
)
\displaystyle\sum_{i=1}^k\left(C_{k}^{i}(\frac 1{100})^i(\frac {99}{100})^{k-i}\right)
i=1∑k?(Cki?(1001?)i(10099?)k?i),也就说,当
k
k
k 取定时,只有
(
99
100
)
k
(\frac{99}{100})^k
(10099?)k 的分组不用重新检测,所用的试剂盒个数为
N
k
+
N
(
1
?
(
99
100
)
k
)
\frac Nk + N(1-(\frac{99}{100})^k)
kN?+N(1?(10099?)k)。
??设函数
f
(
x
)
=
N
x
+
N
(
1
?
(
99
100
)
x
)
f(x) = \frac Nx+N(1-(\frac{99}{100})^x)
f(x)=xN?+N(1?(10099?)x),
N
N
N 为一个较大常数,
f
′
(
x
)
=
?
N
x
2
?
N
ln
?
99
100
(
99
100
)
x
=
?
N
(
x
?
2
+
ln
?
99
100
(
99
100
)
x
)
f'(x) = -\frac N{x^2} - N\ln\frac{99}{100}(\frac{99}{100})^x = -N(x^{-2} + \ln\frac{99}{100}(\frac{99}{100})^x)
f′(x)=?x2N??Nln10099?(10099?)x=?N(x?2+ln10099?(10099?)x),大致能看出
f
(
x
)
f(x)
f(x) 在
[
1
,
100
)
[1,100)
[1,100) 的极小值在
(
10
,
11
)
(10,11)
(10,11) 之间,可以说
10
10
10、
11
11
11 都是对的。
??但赛委组怎么考虑这道题的,我就不得而知了。
#C 分配口罩
本题总分:
10
10
10 分
问题描述
??某市市长获得了若干批口罩,每一批口罩的数目如下:(如果你把以下文字复制到文本文件中,请务必检查复制的内容是否与文档中的一致。在试题目录下有一个文件 mask.txt,内容与下面的文本相同)
9090400
8499400
5926800
8547000
4958200
4422600
5751200
4175600
6309600
5865200
6604400
4635000
10663400
8087200
4554000
??现在市长要把口罩分配给市内的 2 所医院。由于物流限制,每一批口罩只能全部分配给其中一家医院。市长希望 2 所医院获得的口罩总数之差越小越好。请你计算这个差最小是多少?
答案提交
??这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
2400
#include <stdio.h>
int n, i, cnt, sum, ans = 0x3F3F3F3F, A[1000];
int abs(int a) { return a > 0 ? a : -a; }
int main() {
freopen("mask.txt", "r", stdin);
while (~scanf("%d", &A[n])) sum += A[n++];
for (int k = 1 << n; --k;) {
for (cnt = i = 0; i < n; ++i)
if (k >> i & 1) cnt += A[i];
if (abs(sum - 2 * cnt) < ans) ans = abs(sum - 2 * cnt);
}
printf("%d", ans);
}
??
n
n
n 比较小,可以直接枚举所有可能的分配,当
n
n
n 大了可以尝试在
m
a
p
\mathrm{map}
map 上做个背包
d
p
\mathrm{dp}
dp,但写起来可能有点恶心,这里就不实现了。
#D 矩阵
本题总分:
10
10
10 分
问题描述
??把
1
~
2020
1 \sim 2020
1~2020 放在
2
×
1010
2 × 1010
2×1010 的矩阵里。要求同一行中右边的比左边大,同一 列中下边的比上边的大。一共有多少种方案? ??答案很大,你只需要给出方案数除以
2020
2020
2020 的余数即可。
答案提交
??这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
1340
动态规划
勾长公式
??将
2
×
1010
2 × 1010
2×1010 的矩阵看作杨表,则其方案数有勾长公式
dim
?
π
λ
=
n
!
∏
x
∈
Y
(
λ
)
h
o
o
k
(
x
)
=
2020
!
1011
!
1010
!
(
m
o
d
2020
)
\dim \pi _\lambda=\cfrac {n!}{\prod_{x\in Y(\lambda)}{\mathrm{hook}}(x)} = \cfrac{2020!}{1011!1010!} \pmod {2020}
dimπλ?=∏x∈Y(λ)?hook(x)n!?=1011!1010!2020!?(mod2020)
??由于模数非质、因子较小且连续,故不采用扩展欧几里得求逆元,直接统计质因子质数再将其相乘即可。
#include <bits/stdc++.h>
using namespace std;
map<int, int> factor[2021];
vector<int> primes;
int ans = 1;
int main() {
for (int i = 2; i <= 2020; ++i) {
if (!factor[i][0]) {
primes.push_back(i);
factor[i][i] = 1;
}
for (int p : primes) {
if (p * i > 2020) break;
factor[p * i] = factor[i];
factor[p * i][0] = 1;
factor[p * i][p]++;
if (i % p == 0) break;
}
}
for (int i = 1; i <= 1010; ++i)
for (auto &p : factor[i]) factor[2020][p.first] -= p.second;
for (int i = 1012; i < 2020; ++i)
for (auto &p : factor[i]) factor[2020][p.first] += p.second;
for (auto &p : factor[2020])
for (int i = 0; i < p.second; ++i) if (p.first) ans = ans * p.first % 2020;
printf("%d", ans);
}
??上当了,应该用扩欧的。
??当然,如果会点
P
y
t
h
o
n
\mathrm {Python}
Python 的话:
ans = 1
for i in range(1, 1011):
ans = ans * (i + 1011) // i
print(ans % 2020)
#E 完美平方数
本题总分:
15
15
15 分
问题描述
??如果一个整数本身是完全平方数,它的每一位组成数字也是完全平方数,我们就称它是完美平方数。
??前几个完美平方数是
0
、
1
、
4
、
9
、
49
、
100
、
144
?
?
0、1、4、9、49、100、144\cdots\cdots
0、1、4、9、49、100、144??
??即第
1
1
1 个完美平方数是
0
0
0,第
2
2
2 个是
1
1
1,第
3
3
3 个是
4
4
4,
?
?
\cdots\cdots
??
??那么,第
2020
2020
2020 个完美平方数是多少?
答案提交
??这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
1499441040
#include <stdio.h>
int N = 2020, ans = 0;
bool check(int n) { return !n || n == 1 || n == 4 || n == 9; }
int main() {
while (N) {
bool flag = 1;
for (int n = ans * ans; n; n /= 10)
if(!check(n % 10)) flag = 0;
if (flag) --N;
if (N) ans++;
}
printf("%d", ans * ans);
}
??设答案与
N
=
2020
N = 2020
N=2020 的关系为
f
(
N
)
f(N)
f(N),则对于几种常见的枚举对象,它们的复杂度是。
??
O
(
f
(
N
)
)
O(f(N))
O(f(N)),枚举
1
~
f
(
x
)
1\sim f(x)
1~f(x) 中的每一个数。
??
O
(
4
log
?
f
(
N
)
)
O(4^{\log f(N)})
O(4logf(N)),枚举
1
~
f
(
x
)
1\sim f(x)
1~f(x) 中的能被
0
,
1
,
4
,
9
0, 1,4, 9
0,1,4,9 组合成的数。
??
O
(
f
(
N
)
)
O(\sqrt{f(N)})
O(f(N)
?),枚举
1
~
f
(
x
)
1\sim f(x)
1~f(x) 中的完全平方数。
??对于第一种,它的运行耗时显然不是我们所能接受,对于第二种则需要我们对于答案的特征,如它的位数有着快速准确的判断,来避免在调试程序花费不必要的时间。
??总之保持对时间复杂度的敏感程度,至少可以避免你选择到最差解。
#F 解码
时间限制:
1.0
s
1.0\mathrm s
1.0s 内存限制:
256.0
M
B
256.0\mathrm{MB}
256.0MB 本题总分:
15
15
15 分
问题描述
??小明有一串很长的英文字母,可能包含大写和小写。 ??在这串字母中,有很多连续的是重复的。小明想了一个办法将这串字母表达得更短:将连续的几个相同字母写成字母
+
+
+ 出现次数的形式。 ??例如,连续的
5
5
5 个
a
\mathrm a
a ,即
a
a
a
a
a
\mathrm{aaaaa}
aaaaa ,小明可以简写成
a
5
\mathrm{a5}
a5 (也可能简写成
a
4
a
\mathrm{a4a}
a4a 、
a
a
3
a
\mathrm{aa3a}
aa3a 等)。 ??对于这个例子:
H
H
H
e
l
l
l
l
l
o
o
\mathrm{HHHellllloo}
HHHellllloo ,小明可以简写成
H
3
e
l
5
o
2
\mathrm{H3el5o2}
H3el5o2。为了方便表达,小明不会将连续的超过
9
9
9 个相同的字符写成简写的形式。 ??现在给出简写后的字符串,请帮助小明还原成原来的串。
输入格式
??输入一行包含一个字符串。
输出格式
??输出一个字符串,表示还原后的串。
测试样例1
Input:
H3el5o2
Output:
HHHellllloo
评测用例规模与约定
??对于所有评测用例,字符串由大小写英文字母和数字组成,长度不超过
100
100
100。 ??请注意原来的串长度可能超过
100
100
100。
#include <stdio.h>
char s[2020];
int main() {
scanf("%s", s);
for (int i = 0; s[i]; ++i) {
if (s[i] > '9') putchar(s[i]);
else while (s[i]-- > '1') putchar(s[i - 1]);
}
}
??签到。
#G 走方格
时间限制:
1.0
s
1.0\mathrm s
1.0s 内存限制:
256.0
M
B
256.0\mathrm{MB}
256.0MB 本题总分:
20
20
20 分
问题描述
??在平面上有一些二维的点阵。 ??这些点的编号就像二维数组的编号一样,从上到下依次为第
1
1
1 至第
n
n
n 行,从左到右依次为第
1
1
1 至第
m
m
m 列,每一个点可以用行号和列号来表示。 ??现在有个人站在第
1
1
1 行第
1
1
1 列,要走到第
n
n
n 行第
m
m
m 列。 ??只能向右或者向下走。 ??注意,如果行号和列数都是偶数,不能走入这一格中。 ??问有多少种方案。
输入格式
??输入一行包含两个整数
n
,
m
n,m
n,m。
输出格式
??输出一个整数,表示答案。
测试样例1
Input:
3 4
Output:
2
评测用例规模与约定
??对于所有评测用例,
1
≤
n
≤
30
,
1
≤
m
≤
30
1 \leq n \leq 30, 1 \leq m \leq 30
1≤n≤30,1≤m≤30。
#include <stdio.h>
int n, m, dp[50][50] = {0, 1};
int main() {
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
if (i & 1 || j & 1) dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
printf("%d", dp[n][m]);
}
??二连签到。
#H 整数小拼接
时间限制:
1.0
s
1.0\mathrm s
1.0s 内存限制:
256.0
M
B
256.0\mathrm{MB}
256.0MB 本题总分:
20
20
20 分
问题描述
??给定一个长度为
n
n
n 的数组
A
1
,
A
2
,
?
?
,
A
n
A_1,A_2,\cdots,A_n
A1?,A2?,?,An?。你可以从中选出两个数
A
i
A_i
Ai? 和
A
j
A_j
Aj? (
i
i
i 不等于
j
j
j) ,然后将
A
i
A_i
Ai? 和
A
j
A_j
Aj? 一前一后拼成一个新的整数。例如
12
12
12 和
345
345
345 可以拼成
12345
12345
12345 或
34512
34512
34512 。注意交换
A
i
A_i
Ai? 和
A
j
A_j
Aj? 的顺序被视为
2
2
2 种拼法,即便是
A
i
=
A
j
A_i=A_j
Ai?=Aj? 时。 ??请你计算有多少种拼法满足拼出的整数小于等于
K
K
K。
输入格式
??第一行包含
2
2
2 个整数
n
n
n 和
K
K
K。 ??第二行包含
n
n
n 个整数
A
1
,
A
2
,
?
?
,
A
n
A_1,A_2,\cdots,A_n
A1?,A2?,?,An?。
输出格式
??输出一个整数,表示答案。
测试样例1
Input:
4 33
1 2 3 4
Output:
8
评测用例规模与约定
??对于
30
30
30% 的评测用例,
1
≤
n
≤
1000
,
1
≤
K
≤
1
0
8
,
1
≤
A
i
≤
1
0
4
1\leq n \leq 1000, 1 \leq K \leq 10^8, 1 \leq A_i \leq 10^4
1≤n≤1000,1≤K≤108,1≤Ai?≤104。 ??对于所有评测用例,
1
≤
n
≤
100000
,
1
≤
K
≤
1
0
10
,
1
≤
A
i
≤
1
0
9
1\leq n \leq 100000, 1 \leq K \leq 10^{10}, 1 \leq A_i \leq 10^9
1≤n≤100000,1≤K≤1010,1≤Ai?≤109。
#include <algorithm>
#include <stdio.h>
long long K, ans, A[100010];
int n;
int main() {
scanf("%d %lld", &n, &K);
for (int i = 0; i < n; ++i)
scanf("%d", &A[i]);
std::sort(A, &A[n]);
for (int i = 0; i < n; ++i) {
long long k = 1;
while (A[i] >= k) k *= 10;
long long *find = std::upper_bound(A, &A[n], K / k - (K % k < A[i]));
if (find > &A[i]) --ans;
ans += find - A;
}
printf("%lld", ans);
}
??签到三连。
??
S
T
L
\mathrm{STL}
STL 好用的想转
C
\mathrm C
C。
#I 超级胶水
时间限制:
1.0
s
1.0\mathrm s
1.0s 内存限制:
256.0
M
B
256.0\mathrm{MB}
256.0MB 本题总分:
25
25
25 分
问题描述
??小明有
n
n
n 颗石子,按顺序摆成一排,他准备用胶水将这些石子粘在一起。 ??每颗石子有自己的重量,如果将两颗石子粘在一起,将合并成一颗新的石子,重量是这两颗石子的重量之和。 ??为了保证石子粘贴牢固,粘贴两颗石子所需要的胶水与两颗石子的重量乘积成正比,本题不考虑物理单位,认为所需要的胶水在数值上等于两颗石子重量的乘积。 ??每次合并,小明只能合并位置相邻的两颗石子,并将合并出的新石子放在原来的位置。 ??现在,小明想用最少的胶水将所有石子粘在一起,请帮助小明计算最少需要多少胶水。
输入格式
??输入的第一行包含一个整数
n
n
n,表示初始时的石子数量。 ??第二行包含
n
n
n 个整数
w
1
,
w
2
,
…
,
w
n
w_1 , w_2 , … , w_n
w1?,w2?,…,wn??,依次表示每颗石子的重量。
输出格式
??输出一行包含一个整数,表示最少需要的胶水数。
测试样例1
Input:
3
3 4 5
Output:
47
测试样例2
Input:
8
1 5 2 6 3 7 4 8
Output:
546
评测用例规模与约定
??对于
20
20
20% 的评测用例,
1
≤
n
≤
15
1\leq n \leq 15
1≤n≤15。 ??对于
60
60
60% 的评测用例,
1
≤
n
≤
100
1\leq n \leq 100
1≤n≤100。 ??对于
80
80
80% 的评测用例,
1
≤
n
≤
1000
1\leq n \leq 1000
1≤n≤1000。 ??对于所有评测用例,
1
≤
n
≤
100000
,
1
≤
w
i
≤
1000
1\leq n \leq 100000, 1 \leq w_i \leq 1000
1≤n≤100000,1≤wi?≤1000。
#J 网络分析
时间限制:
1.0
s
1.0\mathrm s
1.0s 内存限制:
256.0
M
B
256.0\mathrm{MB}
256.0MB 本题总分:
25
25
25 分
问题描述
??小明正在做一个网络实验。 ??他设置了
n
n
n 台电脑,称为节点,用于收发和存储数据。 ??初始时,所有节点都是独立的,不存在任何连接。 ??小明可以通过网线将两个节点连接起来,连接后两个节点就可以互相通信了。两个节点如果存在网线连接,称为相邻。 ??小明有时会测试当时的网络,他会在某个节点发送一条信息,信息会发送到每个相邻的节点,之后这些节点又会转发到自己相邻的节点,直到所有直接或间接相邻的节点都收到了信息。所有发送和接收的节点都会将信息存储下来。一条信息只存储一次。 ??给出小明连接和测试的过程,请计算出每个节点存储信息的大小。
输入格式
??输入的第一行包含两个整数
n
,
m
n, m
n,m,分别表示节点数量和操作数量。节点从
1
1
1 至
n
n
n 编号。 ??接下来
m
m
m 行,每行三个整数,表示一个操作。 ??如果操作为
1
?
a
?
b
1\ a\ b
1?a?b,表示将节点
a
a
a 和节点
b
b
b 通过网线连接起来。当
a
=
b
a = b
a=b 时,表示连接了一个自环,对网络没有实质影响。 ??如果操作为
2
?
p
?
t
2\ p\ t
2?p?t,表示在节点
p
p
p 上发送一条大小为
t
t
t 的信息。
输出格式
??输出一行,包含
n
n
n 个整数,相邻整数之间用一个空格分割,依次表示进行完上述操作后节点
1
1
1 至节点
n
n
n 上存储信息的大小。
测试样例1
Input:
4 8
1 1 2
2 1 10
2 3 5
1 4 1
2 2 2
1 1 2
1 2 4
2 2 1
Output:
13 13 5 3
评测用例规模与约定
??对于
30
30
30% 的评测用例,
1
≤
n
≤
20
,
1
≤
m
≤
100
1 ≤ n ≤ 20,1 ≤ m ≤ 100
1≤n≤20,1≤m≤100。 ??对于
50
50
50% 的评测用例,
1
≤
n
≤
100
,
1
≤
m
≤
1000
1 ≤ n ≤ 100,1 ≤ m ≤ 1000
1≤n≤100,1≤m≤1000。 ??对于
70
70
70% 的评测用例,
1
≤
n
≤
1000
,
1
≤
m
≤
10000
1 ≤ n ≤ 1000,1 ≤ m ≤ 10000
1≤n≤1000,1≤m≤10000。 ??对于所有评测用例,
1
≤
n
≤
10000
,
1
≤
m
≤
100000
,
1
≤
t
≤
100
1 ≤ n ≤ 10000,1 ≤ m ≤ 100000,1 ≤ t ≤ 100
1≤n≤10000,1≤m≤100000,1≤t≤100。
|