BUCTOJ - 2023上半年ACM&蓝桥杯每周训练题-1-A~K题C++Python双语版
Posted Tisfy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BUCTOJ - 2023上半年ACM&蓝桥杯每周训练题-1-A~K题C++Python双语版相关的知识,希望对你有一定的参考价值。
文章目录
- BUCTOJ - 2023上半年ACM&蓝桥杯每周训练题-1-A~K题C++Python双语版
- 前言
- The End
BUCTOJ - 2023上半年ACM&蓝桥杯每周训练题-1-A~K题C++Python双语版
知识点:题解, BUCTOJ, 中等, 数组, 递归, 动态规划, 循环, 模拟, 素数, 质数, 贪心, 排序, 图论, 图, 迪杰斯特拉, Dijstra, 树, 哈夫曼树, 最小生成树, 归并排序
前言
这篇题解写包含《2023上半年ACM&蓝桥杯每周训练题-1》的A~K题的解析以及C++和Python双版本代码
蒟蒻的我为了《问题 H: 2.5 一场说走就走的旅行》还心血来潮地做了个无人问津的视频,也耽误了不少时间,导致题解现在才完成至这个模样。
PDF不能播放视频,且一段代码可能会分页显示,因此还是比较推荐在网页端看题解的。地址:https://leetcode.letmefly.xyz/2023/02/21/BUCT-BUCT2023LanQiaoWeekly1
若想查找某一知识点,可以直接Ctrl + F。
问题 A: 1.2 神奇兔子数列
知识点:数组,递归,动态规划
题目描述
假设第 1 个月有 1 对刚诞生的兔子,第 2 个月进入成熟期,第 3 个月开始生育兔子,而1 对成熟的兔子每月会生 1 对兔子,兔子永不死去……那么,由 1 对初生兔子开始,12 个月后会有多少对兔子呢?
兔子数列即斐波那契数列,它的发明者是意大利数学家列昂纳多·斐波那契(Leonardo Fibonacci,1170—1250)。1202 年,他撰写了《算盘全书(《Liber Abaci》)一书,该书是一部较全面的初等数学著作。书中系统地介绍了印度—阿拉伯数码及其演算法则,介绍了中国的“盈不足术”;引入了负数,并研究了一些简单的一次同余式组。
输入
无
输出
一个整数(12个月后有多少对兔子)
解题思路
这道题就是要求斐波那契数列的第12项
在计算斐波那契数列的过程中,我们只需要关注连续的3项。
使用两个变量_1和_2代表已经计算出的第一项和第二项,那么要计算出的第三项_3就等于 1 + 2 _1 + _2 1+2
如此往复,更新第一项和第二项为原来的第二项和第三项,就能不断求出新的第三项。
AC代码
C++
#include <bits/stdc++.h>
using namespace std;
#define mem(a) memset(a, 0, sizeof(a))
#define dbg(x) cout << #x << " = " << x << endl
#define fi(i, l, r) for (int i = l; i < r; i++)
#define cd(a) scanf("%d", &a)
typedef long long ll;
int main()
ll _1 = 1, _2 = 1, _3;
for (int i = 3; i <= 12; i++)
_3 = _1 + _2;
_1 = _2, _2 = _3;
cout << _3 << endl;
return 0;
Python
_1, _2, _3 = 1, 1, ''
for i in range(3, 13):
_3 = _1 + _2
_1, _2 = _2, _3
print(_3)
问题 B: 1.3 马克思手稿中的数学题
知识点:循环,模拟
题目描述
马克思手稿中有一道趣味数学问题:有 30 个人,其中有男人、女人和小孩,这些人在一家饭馆吃饭花了 50 先令;每个男人花 3 先令,每个女人花 2 先令,每个小孩花 1 先令;问男人、女人和小孩各有几人?
输入
无
输出
输出所有可能的解
每行三个整数x,y,z(用空格隔开,x代表男人,y代表女人,z代表小孩,按x升序排列):
x y z
解题思路
数据量并不大,我们暴力枚举0到30范围内的所有x、y、z即可。
注意题目中说“其中有男人、女人和小孩”,也就是说每种人都有,不能为0。
AC代码
C++
#include <bits/stdc++.h>
using namespace std;
#define mem(a) memset(a, 0, sizeof(a))
#define dbg(x) cout << #x << " = " << x << endl
#define fi(i, l, r) for (int i = l; i < r; i++)
#define cd(a) scanf("%d", &a)
typedef long long ll;
int main()
fi (x, 1, 31)
fi (y, 1, 31)
fi (z, 1, 31)
if (x + y + z == 30 && 3 * x + 2 * y + z == 50)
cout << x << ' ' << y << ' ' << z << endl;
return 0;
Python
for x in range(1, 31):
for y in range(1, 31):
for z in range(1, 31):
if x + y + z == 30 and 3 * x + 2 * y + z == 50:
print(x, y, z)
问题 C: 1.4 爱因斯坦的阶梯
知识点:模拟
题目描述
爱因斯坦家里有一条长阶梯,若每步跨 2 阶,则最后剩 1 阶;若每步跨 3 阶,则最后剩 2 阶;若每步跨 5 阶,则最后剩 4 阶;若每步跨 6 阶,则最后剩 5 阶。只有每次跨 7 阶,最后才正好 1 阶不剩。请问这条阶梯共有多少阶?
输入
无
输出
满足题目的最小整数
解题思路
从1开始往上模拟即可
AC代码
C++
#include <bits/stdc++.h>
using namespace std;
#define mem(a) memset(a, 0, sizeof(a))
#define dbg(x) cout << #x << " = " << x << endl
#define fi(i, l, r) for (int i = l; i < r; i++)
#define cd(a) scanf("%d", &a)
typedef long long ll;
int main()
int ans = 1;
while (true)
if (ans % 2 == 1 && ans % 3 == 2 && ans % 5 == 4 && ans % 6 == 5 && ans % 7 == 0)
cout << ans << endl;
break;
ans++;
return 0;
Python
ans = 1
while True:
if ans % 2 == 1 and ans % 3 == 2 and ans % 5 == 4 and ans % 6 == 5 and ans % 7 == 0:
print(ans)
break
ans += 1
问题 D: 1.5 哥德巴赫猜想
知识点:模拟、素数/质数
题目描述
哥德巴赫猜想:任一大于 2 的偶数,都可表示成两个素数之和。
验证:2000 以内大于 2 的偶数都能够分解为两个素数之和。
输入
无
输出
2000 以内大于 2 的偶数被分解的两个素数
按升序排列,第一个素数为最小值
4=2+2
6=3+3
8=3+5
10=3+7
12=5+7
14=3+11
16=3+13
......
解题思路
题目数据范围不大,我们可以先求出2000以内的素数并放入数组和哈希表中,接着对于某个偶数,从最小的素数开始尝试,快速得到 偶数 − 这个素数 偶数-这个素数 偶数−这个素数是否也为素数。若是则输出,否则尝试大一点的素数。
AC代码
C++
#include <bits/stdc++.h>
using namespace std;
#define mem(a) memset(a, 0, sizeof(a))
#define dbg(x) cout << #x << " = " << x << endl
#define fi(i, l, r) for (int i = l; i < r; i++)
#define cd(a) scanf("%d", &a)
typedef long long ll;
bool isPrime(int n)
int k = sqrt(n);
for (int i = 2; i <= k; i++)
if (n % i == 0)
return false;
return true;
int main()
vector<int> prime;
unordered_set<int> se;
for (int i = 2; i <= 2000; i++)
if (isPrime(i))
prime.push_back(i);
se.insert(i);
for (int i = 4; i <= 2000; i += 2)
for (int t : prime)
if (se.count(i - t))
printf("%d=%d+%d\\n", i, t, i - t);
break;
return 0;
Python
from math import sqrt
def isPrime(n):
k = int(sqrt(n))
for i in range(2, k + 1):
if n % i == 0:
return False
return True
prime = []
se = set()
for i in range(2, 2001):
if isPrime(i):
prime.append(i)
se.add(i)
for i in range(4, 2001, 2):
for t in prime:
if i - t in se:
print(f"i=t+i-t")
break
问题 E: 2.2 加勒比海盗船
知识点:贪心
题目描述
在北美洲东南部,有一片神秘的海域,那里碧海蓝天、阳光明媚,这正是传说中海盗最活跃的加勒比海(Caribbean Sea)。17 世纪时,这里更是欧洲大陆的商旅舰队到达美洲的必经之地,所以当时的海盗活动非常猖獗,海盗不仅攻击过往商人,甚至攻击英国皇家舰……
有一天,海盗们截获了一艘装满各种各样古董的货船,每一件古董都价值连城,一旦打碎就失去了它的价值。虽然海盗船足够大,但载重量为 C,每件古董的重量为 wi,海盗们该如何把尽可能多数量的宝贝装上海盗船呢?
输入
请输入问题的组数 m:
m ( 0 < m < 100 )
请输入载重量 c 及古董个数 n:
c n (0 < c, n < 10000)
请输入每个古董的重量,用空格分开:
w1 w2 w3 ... wn (0 < wi < 100)
输出
能装入的古董最大数量为:
ans
输入样例
1
30 8
4 10 7 11 3 5 14 2
输出样例
5
解题思路
装载数量优先,那必是先装重量小的。
AC代码
C++
#include <bits/stdc++.h>
using namespace std;
#define mem(a) memset(a, 0, sizeof(a))
#define dbg(x) cout << #x << " = " << x << endl
#define fi(i, l, r) for (int i = l; i < r; i++)
#define cd(a) scanf("%d", &a)
typedef long long ll;
int a[10010];
int main()
int T;
cin >> T;
while (T--)
int m, n;
cin >> m >> n;
for (int i = 0; i < n; i++)
scanf("%d", &a[i]);
sort(a, a + n);
int ans = 0;
while (m > 0 && ans < n)
if (m >= a[ans])
m -= a[ans++];
else
break;
cout << ans << endl;
return 0;
Python
T = int(input())
for _ in range(T):
m, n = map(int, input().split())
a = list(map(int, input().split()))
a.sort()
ans = 0
while m > 0 and ans < n:
if m >= a[ans]:
m -= a[ans]
ans += 1
else:
break
print(ans)
问题 F: 2.3 阿里巴巴与四十大盗
知识点:贪心
题目描述
有一天,阿里巴巴赶着一头毛驴上山砍柴。砍好柴准备下山时,远处突然出现一股烟尘,弥漫着直向上空飞扬,朝他这儿卷过来,而且越来越近。靠近以后,他才看清原来是一支马队,他们共有四十人,一个个年轻力壮、行动敏捷。一个首领模样的人背负沉重的鞍袋,从丛林中一直来到那个大石头跟前,喃喃地说道:“芝麻,开门吧!”随着那个头目的喊声,大石头前突然出现一道宽阔的门路,于是强盗们鱼贯而入。阿里巴巴待在树上观察他们,直到他们走得无影无踪之后,才从树上下来。他大声喊道:“芝麻,开门吧!”他的喊声刚落,洞门立刻打开了。
他小心翼翼地走了进去,一下子惊呆了,洞中堆满了财物,还有多得无法计数的金银珠宝,有的散堆在地上,有的盛在皮袋中。突然看见这么多的金银财富,阿里巴巴深信这肯定是一个强盗们数代经营、掠夺所积累起来的宝窟。为了让乡亲们开开眼界,见识一下这些宝物,他想一种宝物只拿一个,如果太重就用锤子凿开,但毛驴的运载能力是有限的,怎么才能用驴子运走最大价值的财宝分给穷人呢?阿里巴巴陷入沉思中……
输入
样例的组数 t
t ( 0 < t < 100 )
宝物数量m和驴子的承载重量 n
m n ( 0 < m, n < 10000 )
第i个宝物的重量和价值 ( 0 < wi, vi < 100 )
w1 v1
w2 v2
...
wm vm
输出
装入宝物的最大价值
输入样例
1
6 19
2 8
6 1
7 9
4 3
10 2
3 4
输出样例
24.6
解题思路
注意题目描述了吗?“如果太重就用锤子凿开”。好家伙,凿开还是宝物的话,那就看哪个宝物的“含金密度”大呗!
接下来我们给每个宝物评分,评分规则是宝物的“密度”( 重量 体积 \\frac重量体积 体积重量)
需要注意的是,这道题数据有误,数据中存在重量为0的宝物,也就是说其分数(密度)无限大。注意这时候不能用“重量 * 分数”来计算其总价值了。
还需要注意的是,题目中没有说明输出格式。经测试得知当答案为整数时输出0位小数,答案非整数时输出一些位的小数,完美贴合C++的cout。
还需要注意的是,题目中没有说明多组输入的格式,样例中的多组输入数据之间是有一个空行的,Python选手需要注意
AC代码
C++
#include <bits/stdc++.h>
using namespace std;
#define mem(a) memset(a, 0, sizeof(a))
#define dbg(x) cout << #x << " = " << x <<以上是关于BUCTOJ - 2023上半年ACM&蓝桥杯每周训练题-1-A~K题C++Python双语版的主要内容,如果未能解决你的问题,请参考以下文章