个人感觉蓝桥杯管的不是很严,可以提前打好快读模板和对拍代码(C/C++组只能使用Dev-cpp),快读模板和对拍代码放在最后了;也可以自己带点吃的喝饮料(比赛时间是9:00 — 13:00,中午有可能会饿)。最后也是成功拿到了一个广东省一等奖。
A. 握手问题(5分)
问题描述
小蓝组织了一场算法交流会议,总共有 50 人参加了本次会议。在会议上,大家进行了握手交流。按照惯例他们每个人都要与除自己以外的其他所有人进行一次握手(且仅有一次)。但有 7 个人,这 7 人彼此之间没有进行握手(但这 7 人与除这 7 人以外的所有人进行了握手)。请问这些人之间一共进行了多少次握手?
注意 A 和 B 握手的同时也意味着 B 和 A 握手了,所以算作是一次握手。
答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
思路
当时拿到题目一看感觉像是一道高中的排列组合,用 就行了
B. 小球反弹(5分)
问题描述
有一长方形,长为 343720 单位长度,宽为 233333 单位长度。在其内部左上角顶点有一小球(无视其体积),其初速度如图所示且保持运动速率不变,分解到长宽两个方向上的速率之比为 dx : dy = 15 : 17。小球碰到长方形的边框时会发生反弹,每次反弹的入射角与反射角相等,因此小球会改变方向且保持速率不变(如果小球刚好射向角落,则按入射方向原路返回)。从小球出发到其第一次回到左上角顶点这段时间里,小球运动的路程为多少单位长度?答案四舍五入保留两位小数。
答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个小数,在提交答案时只填写这个小数,填写多余的内容将无法得分。
思路
当时在考场感觉这道题很麻烦就先跳了,想着最后在回来做,结果最后面时间不够了只能随便蒙一个答案上去(好像没对...)。
C. 好数(10分)
时间限制:1.0s 内存限制:256.0MB
问题描述
一个整数如果按从低位到高位的顺序,奇数位(个位、百位、万位…)上的数字是奇数,偶数位(十位、千位、十万位…)上的数字是偶数,我们就称之为“好数”。
给定一个正整数 N,请计算从 1 到 N 一共有多少个好数。
输入格式
一个整数 N
输出格式
一个正数表示答案
样例输入1
24
样例输出1
7
样例输入2
2024
样例输出2
150
样例说明
对于第一个样例,24 以内的好数有 1、3、5、7、9、21、23,一共 7 个。
评测用例规模与约定
对于 10% 的评测用例,1 ≤ N ≤ 100。
对于 100% 的评测用例,1 ≤ N ≤
思路
正确答案应该是要用数位dp,但是感觉数据量不是很大,所以暴力应该也能过。
代码
#include <bits/stdc++.h>
using namespace std;
inline int read() {
int x = 0, f = 1; char c = getchar();
while (c < '0' || c > '9') {
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
int main() {
int n = read(), cnt = 0;
for (int i = 1; i <= n; i += 2) {
int m = i, t = 0, flag = 1;
while (m) {
if (m % 2 == t) { flag = 0; break; }
m /= 10, t ^= 1;
}
if (flag) cnt++;
}
printf("%d", cnt);
return 0;
}
D. R 格式(10分)
时间限制:1.0s 内存限制:256.0MB
问题描述
小蓝最近在研究一种浮点数的表示方法:R 格式。对于一个大于 0 的浮点数 d,可以用 R 格式的整数来表示。给定一个转换参数 n,将浮点数转换为 R 格式整数的做法是:
1.将浮点数乘以 ;
2.四舍五入到最接近的整数。
输入格式
一行输入一个整数 n 和一个浮点数 d,分别表示转换参数,和待转换的浮点数。
输出格式
输出一行表示答案:d 用 R 格式表示出来的值。
样例输入
2 3.14
样例输出
13
样例说明
,四舍五入后为 13。
评测用例规模与约定
对于 50% 的评测用例:1 ≤ n ≤ 10,1 ≤ 将 d 视为字符串时的长度 ≤ 15。
对于 100% 的评测用例:1 ≤ n ≤ 1000,1 ≤ 将 d 视为字符串时的长度 ≤ 1024;保证 d 是小数,即包含小数点。
思路
因为 ,所以很明显需要用到高精度快速幂(long long 无法存下 )。
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int ans[N], temp[N], a[N], oup[N], n, len, zs, xs;
char d[1030];
inline int read() {
int x = 0, f = 1; char c = getchar();
while (c < '0' || c > '9') {
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
void mul_1()
{
memset(temp, 0, sizeof(temp));
for (int i = 1; i <= 500; i++)
for (int j = 1; j <= 500; j++) temp[i + j - 1] += ans[i] * a[j];
for (int i = 1; i <= 500; i++)
{
temp[i + 1] += temp[i] / 10;
temp[i] %= 10;
}
for (int i = 1; i <= 500; i++) ans[i] = temp[i];
}
void mul_2()
{
memset(temp, 0, sizeof(temp));
for (int i = 1; i <= 500; i++)
for (int j = 1; j <= 500; j++) temp[i + j - 1] += a[i] * a[j];
for (int i = 1; i <= 500; i++)
{
temp[i + 1] += temp[i] / 10;
temp[i] %= 10;
}
for (int i = 1; i <= 500; i++) a[i] = temp[i];
}
int main()
{
n = read(); cin >> d;
for (int i = 0; i < strlen(d); i++) {
if (d[i] == '.') { len = i; break; }
zs = zs * 10 + d[i] - '0';
}
for (int i = len + 1; i < strlen(d); i++) {
xs = xs * 10 + d[i] - '0';
}
// 将浮点数d拆成整数和小数两部分并且记下整数部分长度
len = strlen(d) - len - 1; // 算出小数部分长度
ans[1] = 1, a[1] = 2;
while (n > 0)
{
if (n % 2 == 1) mul_1();
mul_2();
n /= 2;
} // 利用高精快速幂计算2的n次方
for (int i = 1; i <= len; i++) oup[i] = ans[i] * zs;
for (int i = 1; i <= 500; i++) {
oup[i + 1] += oup[i] / 10;
oup[i] %= 10;
}
for (int i = 1; i <= len; i++) ans[i] *= xs;
for (int i = 1; i <= 500; i++) {
ans[i + 1] += ans[i] / 10;
ans[i] %= 10;
}
if (ans[len] >= 5) ans[len + 1]++; // 四舍五入
for (int i = 1; i <= 500; i++) {
oup[i] += ans[i + len]; // 只加d的小数乘2的n次方后的整数部分
if (oup[i] > 9) {
oup[i + 1] += oup[i] / 10;
oup[i] /= 10;
}
} // 将整数小数部分分别乘上2的n次方
int p;
for (int i = 500; i; i--) {
if (oup[i]) {
p = i;
break;
}
} // 记下第一位的位置
for (int i = p; i; i--) putchar(oup[i] + '0'); // 按位输出
return 0;
}
E. 宝石组合(15分)
时间限制:1.0s 内存限制:256.0MB
问题描述
在一个神秘的森林里,住着一个小精灵名叫小蓝。有一天,他偶然发现了一个隐藏在树洞里的宝藏,里面装满了闪烁着美丽光芒的宝石。这些宝石都有着不同的颜色和形状,但最引人注目的是它们各自独特的“闪亮度”属性。每颗宝石都有一个与生俱来的特殊能力,可以发出不同强度的闪光。小蓝共找到了 N 枚宝石,第 i 枚宝石的“闪亮度”属性值为 ,小蓝将会从这 N 枚宝石中选出三枚进行组合,组合之后的精美程度 S 可以用以下公式来衡量:
其中 LCM 表示的是最小公倍数函数。
小蓝想要使得三枚宝石组合后的精美程度 S 尽可能的高,请你帮他找出精美程度最高的方案。如果存在多个方案 S 值相同,优先选择按照 H 值升序排列后字典序最小的方案。
输入格式
第一行包含一个整数 N 表示宝石个数。
第二行包含 N 个整数表示 N 个宝石的“闪亮度”。
输出格式
输出一行包含三个整数表示满足条件的三枚宝石的“闪亮度”。
样例输入
样例输出
评测用例规模与约定
对于 30% 的评测用例:3 ≤ N ≤ 100,1 ≤ ≤ 1000。
对于 60% 的评测用例:3 ≤ N ≤ 2000。
对于 100% 的评测用例:3 ≤ N ≤ ,1 ≤ ≤10
F. 数字接龙(15分)
时间限制:1.0s 内存限制:256.0MB
问题描述
小蓝最近迷上了一款名为《数字接龙》的迷宫游戏,游戏在一个大小为 N x N 的格子棋盘上展开,其中每一个格子处都有着一个 0 … K - 1 之间的整数。游戏规则如下:
1. 从左上角(0,0)处出发,目标是到达右下角(N - 1,N - 1)处的格子,每一步可以选择沿着水平/垂直/对角线方向移动到下一个格子。
2. 对于路径经过的棋盘格子,按照经过的格子顺序,上面的数字组成的序列要满足:0,1,2,...,K - 1,0,1,2,...,K - 1,0,1,2 ...。
3. 途中需要对棋盘上的每个格子恰好都经过一次(仅一次)。
4. 路径中不可以出现交叉的线路。例如之前有从(0,0)移动到(1,1),那么再从(1,0)移动到(0,1)线路就会交叉。
为了方便表示,我们对可以行进的所有八个方向进行了数字编号,如下图 2 所示:因此行进路径可以用一个包含 0 ... 7 之间的数字字符串表示,如下图 1 是一个迷宫示例,它所对应的答案就是:41255214。
现在请你帮小蓝规划出一条行进路径并将其输出。如果有多条路径,输出字典序最小的那一个:如果不存在任何一条路径,则输出 -1。
输入格式
第一行包含两个整数 N,K。
接下来输入 N 行,每行 N 个整数表示棋盘格子上的数字。
输出格式
输出一行表示答案。如果存在答输出路径,否则输出 -1。
样例输入
样例输出
样例说明
行进路径如图 1 所示。
评测用例规模与约定
对于 80% 的评测用例:1 ≤ N ≤ 5。
对于 100%的评测用例:1 ≤ N ≤ 10,1 ≤ K ≤ 10。
思路
本题数据量非常小所以可以考虑直接搜索,深搜广搜应该都行,看个人习惯。
G. 爬山(20分)
时间限制:1.0s 内存限制:256.0MB
问题描述
小明这天在参加公司团建,团建项目是爬山。在 x 轴上从左到右一共有座山,第 i 座山的高度为 。他们需要从左到右依次爬过所有的山,需要花费的体力值为。
然而小明偷偷学了魔法,可以降低一些山的高度。他掌握两种魔法,第一种魔法可以将高度为 H 的山的高度变为 ,可以使用 P 次;第二种魔法可以将高度为 H 的山的高度变为 ,可以使用 Q 次。并且对于每座山可以按任意顺序多次释放这两种魔法。
小明想合理规划在哪些山使用魔法,使得爬山花费的体力值最少。请问最优情况下需要花费的体力值是多少?
输入格式
输入共两行。
第一行为三个整数 n,P,Q。
第二行为 n 个整数 。
输出格式
输出共一行,一个整数代表答案。
样例输入
样例输出
样例说明
将第四座山变为 ,然后再将第四座山变为 。
体力值为 4 + 5 + 6 + 3 = 18。
评测用例规模与约定
对于 20% 的评测用例,保证 n ≤ 8,P = 0。
对于 100% 的评测用例,保证 n ≤ 100000,0 ≤ P ≤ n,0 ≤ Q ≤ n,0 ≤ ≤ 100000。
代码
暴力代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e5 + 10;
int n, p, q, h[N], sum = 0;
inline int read() {
int x = 0, f = 1; char c = getchar();
while (c < '0' || c > '9') {
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
signed main() {
n = read(), p = read(), q = read();
for (int i = 1; i <= n; i++) h[i] = read();
for (int i = 1; i <= p; i++) {
sort(h + 1, h + n + 1);
h[n] = sqrt(h[n]);
}
for (int i = 1; i <= q; i++) {
sort(h + 1, h + n + 1);
h[n] /= 2;
}
for (int i = 1; i <= n; i++) sum += h[i];
printf("%lld", sum);
return 0;
}
H. 拔河(20分)
时间限制:1.0s 内存限制:256.MB
问题描述
小明是学校里的一名老师,他带的班级共有 n 名同学,第 i 名同学力量值为 。在闲暇之余,小明决定在班级里组织一场拔河比赛。
为了保证比赛的双方实力尽可能相近,需要在这 n 名同学中挑选出两个队伍,队伍内的同学编号连续: 和 ,其中 。
两个队伍的人数不必相同,但是需要让队伍内的同学们的力量值之和尽可能相近。请计算出力量值之和差距最小的挑选队伍的方式。
输入格式
输入共两行。
第一行为一个正整数 n。
第二行为 n 个正整数 。
输出格式
输出共一行,一个非负整数,表示两个队伍力量值之和的最小差距。
样例输入
样例输出
样例说明
其中一种最优选择方式:
队伍 1:,队伍 2:,力量值和分别为 10 + 9 + 8 = 27,12 + 14 = 26,差距为|27 - 26| = 1。
评测用例规模与约定
对于 20% 的评测用例,保证 n ≤ 50。
对于 100% 的评测用例,保证 n ≤ ,a ≤ 。
快读模板
inline int read() {
int x = 0, f = 1; char c = getchar();
while (c < '0' || c > '9') {
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
}
如果题目中有的变量需要用 long long 的话,可以直接在宏里面把 int 扩展到 long long,这样比较方便(如下图)。
#include <bits/stdc++.h>
using namespace std;
#define int long long
inline int read() {
int x = 0, f = 1; char c = getchar();
while (c < '0' || c > '9') {
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
}
// 代码
signed main() {
// 代码
return 0;
}
对拍代码
整个对拍需要以下文件。bf.cpp文件里是暴力代码,std.cpp文件里是用了算法的代码,data.cpp用来生成输入样例,pai.cpp用来比较bf.cpp和stdcpp.out的结果是否相同。
注意:每次更改bf.cpp,std.cpp或data.cpp之后都需要重新编译之后再运行pai.cpp进行对拍。
接下来以输出 a + b 的程序来说明。
bf.cpp
#include <bits/stdc++.h>
using namespace std;
int main() {
int a, b, oup = 0;
cin >> a >> b;
for (int i = 1; i <= a; i++) oup++;
for (int i = 1; i <= b; i++) oup++;
cout << oup;
return 0;
}
std.cpp
#include <bits/stdc++.h>
using namespace std;
int main() {
int a, b;
cin >> a >> b;
if (a > 0) cout << a << endl;
cout << a + b << endl;
return 0;
}
data.cpp
#include <bits/stdc++.h>
using namespace std;
int main() {
srand(time(0));
int a = rand(), b = rand(); // 随机生成两个数字
cout << a << ' ' << b << endl; // 按照格式输出
return 0;
}
pai.cpp
可以不用自己创建txt文件,编译运行一次pai.cpp之后会自动生成相应txt文件
#include <bits/stdc++.h>
using namespace std;
int main() {
int t = 1;
while (1) {
printf("test%d: ", t++);
system("data.exe > in.txt"); // 用 data.exe 生成输入样例,并存入 in.txt 文件中
system("std.exe < in.txt > stdout.txt");
// 将 in.txt 文件中的输入样例用来测试 std.cpp 中的代码,并将结果输出到 stdout.txt 文件中
system("bf.exe < in.txt > bfout.txt");
// 将 in.txt 文件中的输入样例用来测试 bf.cpp 中的代码,并将结果输出到 bf.out 文件中
// 比较 stdout.txt 和 bfout.txt 文件是否一样,一样返回 false,不一样返回 true
if (system("fc stdout.txt bfout.txt")) {
cout << "WA\n";
return 0;
}
cout << "AC\n";
}
cout << "AC\n";
}
下图是pai.cpp运行后的输出结果,会显示WA和输出不一样的地方。
如果输出样例一样的话,会一直显示AC。
这个时候接着写下一道题就好了,让它在后台接着运行,有可能后面会出现不一样的地方。