2024年蓝桥杯省赛C/C++大学A组代码
[蓝桥杯 2024 省 A] 艺术与篮球
题目描述
小蓝出生在一个艺术与运动并重的家庭中。
妈妈是位书法家,她希望小蓝能通过练习书法,继承她的艺术天赋,并练就一手好字。爸爸是一名篮球教练,他希望小蓝能通过篮球锻炼身体,培养运
动的激情和团队合作的精神。
为了既满足妈妈的期望,又不辜负爸爸的心意,小蓝决定根据日期的笔画数来安排自己的练习。首先,他会将当天的日期按照 YYYYMMDD
的格式
转换成一个
例如,在
以下是汉字的笔画数对照表:
汉字 | 笔画数 | 汉字 | 笔画数 |
---|---|---|---|
零 | 五 | ||
一 | 六 | ||
二 | 七 | ||
三 | 八 | ||
四 | 九 |
现在,请你帮助小蓝统计一下,在
这段时间内,小蓝有多少天是在练习篮球?
输入格式
这是一道结果填空题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
输出格式
这是一道结果填空题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
解法
模拟
1 |
|
[蓝桥杯 2024 省 A] 五子棋对弈
题目描述
“在五子棋的对弈中,友谊的小船说翻就翻?” 不!对小蓝和小桥来说,五子棋不仅是棋盘上的较量,更是心与心之间的沟通。这两位挚友秉承着 “友谊第一,比赛第二” 的宗旨,决定在一块
比赛遵循以下规则:
- 棋盘规模:比赛在一个
的方格棋盘上进行,共有 个格子供下棋使用。 - 棋子类型:两种棋子,黑棋与白棋,代表双方。小蓝持白棋,小桥持黑棋。
- 先手规则:白棋(小蓝)具有先手优势,即在棋盘空白时率先落子(下棋)。
- 轮流落子:玩家们交替在棋盘上放置各自的棋子,每次仅放置一枚。
- 胜利条件:率先在横线、竖线或斜线上形成连续的五个同色棋子的一方获胜。
- 平局条件:当所有
个棋盘格都被下满棋子,而未决出胜负时,游戏以平局告终。
在这一设定下,小蓝和小桥想知道,有多少种不同的棋局情况(终局不同看成不同情况,终局相同而落子顺序不同看成同一种情况),既确保棋盘下满又保证比赛结果为平局。
输入格式
这是一道结果填空题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
输出格式
这是一道结果填空题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
解法
dfs,模拟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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
const int N=(1e5)+5;
using namespace std;
using ll=unsigned long long;
int arr[26];
/*
* 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
*/
ll ans=0;
void dfs(int d,int b){
if(b>13||d-b>13)
return;
if(d==26){
bool ok=false;
for(int i=7;i<=25;i+=6)
if(arr[1]!=arr[i]){
ok=true;
break;
}
if(ok)
ans++;
return;
}
for(int i=0;i<=1;i++){
arr[d]=i;
if(d%5==0){
bool ok=false;
for(int j=1;j<=4;j++){//0,1,2,3,4
if(arr[d]!=arr[d-j]){
ok=true;
break;
}
}
if(!ok)
continue;
}
if(d==21){
bool ok=false;
for(int j=9;j<=21;j+=4){//5,9,13,17,21
if(arr[5]!=arr[j]){
ok=true;
break;
}
}
if(!ok)
continue;
}
if(d>=21){
bool ok=false;
for(int j=5;j<=20;j+=5){
if(arr[d]!=arr[d-j]){
ok=true;
break;
}
}
if(!ok)
continue;
}
dfs(d+1,b+i);
}
}
int main() {
dfs(1,0);
cout<<ans<<endl;
}
//3126376
[蓝桥杯 2024 省 A] 训练士兵
题目描述
在蓝桥王国中,有
为了确保训练的高效性,王国推出了一种组团训练的方案。该方案包含每位士兵所需的一次训练,且总共只需支付
作为训练指挥官,请你计算出最少需要花费多少金币,才能使得所有的士兵都成为顶尖战士?
输入格式
输入的第一行包含两个整数
接下来的
输出格式
输出一行包含一个整数,表示使所有士兵成为顶尖战士所需的最少金币数。
样例 #1
样例输入 #1
1 | 3 6 |
样例输出 #1
1 | 16 |
提示
花费金币最少的训练方式为:进行
对于
对于所有评测用例,
解法
按照需要训练数,从多往少贪心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
using namespace std;
using ll = long long;
typedef pair<int, int> pp;
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr); // 正式比赛不要用这两行,用scanf和printf
int n, s;
cin >> n >> s;
vector<pair<int, int>> arr(n);
for (int i = 0; i < n; i++)
{
cin >> arr[i].pay >> arr[i].num;
}
sort(arr.begin(), arr.end());
int single_paid = 0, sum = 0, i;
for (i = n - 1; i >= 0; i--)
{
single_paid += arr[i].pay;
if (single_paid >= s) // 从第i个开始往前,集体训练更便宜,使用集体训练
{
break;
}
}
int c;
if (i == -1) // 全都是单独训练便宜
{
i = 0;
c = 0;
}
else
{
c = arr[i].num;
}
sum = c * s;
for (int j = i; j < n; j++)
{
sum += arr[j].pay * (arr[j].num - c);
}
cout << sum << endl;
return 0;
}
[蓝桥杯 2024 省 A] 团建
题目描述
小蓝正在和朋友们团建,有一个游戏项目需要两人合作,两个人分别拿到一棵大小为
两个人需要从各自树的根结点
输入格式
输入的第一行包含两个正整数
第二行包含
第三行包含
接下来
接下来
和
输出格式
输出一行包含一个整数表示答案。
样例 #1
样例输入 #1
1 | 2 2 |
样例输出 #1
1 | 1 |
样例 #2
样例输入 #2
1 | 5 4 |
样例输出 #2
1 | 2 |
提示
对于
对于所有评测用例,
解法
对两个树进行dfs1
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
50
51
52
53
54
55
56
57
58
59
60
61
62
using namespace std;
using ll = long long;
int n[2], res = 0;
vector<vector<int>> node(2);
vector<vector<vector<int>>> g(2);
vector<vector<bool>> vis(2, vector<bool>(N));
void dfs(int u, int v, int d)
{
res = max(res, d);
map<int, int> mp; // tree2 value in tree1 value?不用map,只用双重循环过不了
for (int i = 0, l = g[0][u].size(); i < l; i++)
{
int uu = g[0][u][i];
if (vis[0][uu])
continue;
mp[node[0][uu]] = uu;
}
for (int j = 0, s = g[1][v].size(); j < s; j++)
{
int vv = g[1][v][j];
if (vis[1][vv])
continue;
if (mp.count(node[1][vv]) > 0)
{
int uu = mp[node[1][vv]];
vis[0][uu] = vis[1][vv] = true;
dfs(uu, vv, d + 1);
}
}
}
signed main()
{
for (int i = 0; i < 2; i++)
scanf("%d", &n[i]);
for (int i = 0; i < 2; i++)
{
node[i].resize(n[i] + 1);
for (int j = 1; j <= n[i]; j++)
scanf("%d", &node[i][j]);
}
int u, v;
for (int i = 0; i < 2; i++)
{
g[i].resize(n[i] + 1);
for (int j = 1; j < n[i]; j++)
{
scanf("%d%d", &u, &v);
g[i][u].push_back(v);
g[i][v].push_back(u);
}
}
vis[0][1] = vis[1][1] = true;
if (node[0][1] == node[1][1])
dfs(1, 1, 1);
printf("%d\n", res);
return 0;
}
[蓝桥杯 2024 省 A] 成绩统计
题目描述
小蓝的班上有
绩,才有可能选出
提示:
输入格式
输入的第一行包含三个正整数
第二行包含
输出格式
输出一行包含一个整数表示答案。如果不能满足条件,输出
样例 #1
样例输入 #1
1 | 5 3 1 |
样例输出 #1
1 | 4 |
提示
检查完前三名同学的成绩后,只能选出
检查完前四名同学的成绩后,可以选出
对于
对于
对于所有评测用例,保证
解法
前缀和, 二分
1 |
|
[蓝桥杯 2024 省 A] 因数计数
题目描述
小蓝随手写出了含有
输入格式
输入的第一行包含一个正整数
第二行包含
输出格式
输出一行包含一个整数表示答案。
样例 #1
样例输入 #1
1 | 5 |
样例输出 #1
1 | 4 |
提示
四元组
四元组
四元组
四元组
对于
对于
对于所有评测用例,
解法
样例输入:
找到不同的两对因数1
25
3 6 2 2 7
能找到(1,2), (3,2), (4,2), (3,4), (4,3)五对因数(对于(i,j), i≤j)
四元组,满足四个元素不重叠的两组因数,有{(1,2),(3,4)}, {(1,2),(4,3)},{(3,4),(1,2)},{(4,3),(1,2)}
先写了个直接按题意的代码void baoli()
,造出测试例。
再尝试写了一个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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91/*尝试的笨代码*/
using namespace std;
using ll = long long;
ll res = 0ll;
int n; // 数据数量
int a[N]; // 数据
ll e_sum, e_same; // 边的总数量,端点对应数值相同的边的总数量(双向边总数量)
ll e[N]; // 连接边的数量
void baoli(); // 暴力验证
inline ll c2(int a) // 组合数,n*(n+1)/2,因为最后结果要*2就抵消了
{
return a * (a - 1);
}
signed main()
{
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
}
// baoli();
// return 0;
sort(a, a + n);
for (int i = 0; i < n; i++)
{
for (int j = i + 1; j < n; j++)
{
if (a[j] % a[i] == 0)
{
if (a[i] == a[j])
{
e[i] += 2;
e[j] += 2;
e_sum += 2;
e_same += 2;
}
else
{
e[i]++;
e[j]++;
e_sum++;
}
}
}
}
res = c2(e_sum) + e_same;
for (int i = 0; i < n; i++)
{
// cout << e[i] << ' ';
res -= c2(e[i]);
}
printf("%lld\n", res);
return 0;
}
// 以下是纯暴力验证
int baoli_ans = 0;
int t[4];
void baoli_dfs(int d)
{
if (d == 4)
{
for (int i = 0; i < 4; i++)
for (int j = i + 1; j < 4; j++)
if (t[i] == t[j])
return;
if (a[t[1]] % a[t[0]] == 0 && a[t[3]] % a[t[2]] == 0)
{
baoli_ans++;
}
return;
}
for (int i = 0; i < n; i++)
{
t[d] = i;
baoli_dfs(d + 1);
}
}
void baoli()
{
baoli_dfs(0);
cout << baoli_ans << endl;
}
/*
input:
10
1 2 2 3 3 3 4 5 6 6
//ouput: 564
*/
说明至少思路是对的,只是爆时间了👉👈。换一种方式找它们之间的因数关系。
设点
对每一个因子
时间复杂度:
一个答案: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
using namespace std;
using ll = unsigned long long;
ll n, m; // 数据数量,不重复的数据的数量
ll num[N]; // 不重复数据排列
ll cnt[N]; // 桶
ll e[N]; // 连接到的值不一样的边
ll res; // 结果
inline ll c2(ll a) // 组合数,n*(n+1)/2,因为最后结果要*2就抵消了
{
return a * (a - 1);
}
signed main()
{
scanf("%d", &n);
ll a;
for (register ll i = 0; i < n; i++)
{
scanf("%d", &a);
cnt[a]++;
}
for (register ll i = 1; i <= M; i++)
{
if (cnt[i] == 0)
continue;
num[m++] = i;
res += c2(cnt[i]);
for (register ll j = i * 2; j <= M; j += i)
{
e[i] += cnt[j];
e[j] += cnt[i];
res += cnt[i] * cnt[j];
}
}
res = c2(res);
for (register ll i = 0; i < m; i++)
{
res -= c2(e[num[i]] + 2 * (cnt[num[i]] - 1)) * cnt[num[i]];
res += c2(cnt[num[i]]);
}
cout << res<< endl;
return 0;
}
[蓝桥杯 2024 省 A] 零食采购
题目描述
小蓝准备去星际旅行,出发前想在本星系采购一些零食,星系内有
输入格式
输入的第一行包含两个正整数
第二行包含
接下来
航路将星球
接下来
输出格式
输出
样例 #1
样例输入 #1
1 | 4 2 |
样例输出 #1
1 | 3 |
提示
第一个方案路线为
第二个方案路线为
对于 20% 的评测用例,
对于所有评测用例,
解法
使用最近公共祖先LCA板子,在其中加上状态压缩DP
我博客里的lca: https://misaka-xxw.github.io/2025/02/01/lca/
首先,注意审题,题目里说n个节点,n-1条边,连通图,所以这是一个树。任意选中一个根节点,那么点s到点e的最短路径,就是从s往上走到根节点,再往下走到点e。
1 |
|
[蓝桥杯 2024 省 A] 封印宝石
题目描述
在一次探险中,勇者小蓝发现了
印这些宝石,防止其魔法能量被滥用。
封印宝石会消耗小蓝的体力,具体地,将第
此外,为了避免魔力相冲,每个盒子最多存放一颗宝石(每个宝石也只能放进一个盒子),且任意两个相邻盒子不能存放魔力值相同的宝石,相邻的盒子允许同时为空。
小蓝初始的体力值为
作为勇者小蓝的追随者,请你帮他找出这一放置宝石的方法。
字典序的解释: 在本题中,字典序的大小是按照宝石的魔力值进行比较的。对于两个长度同为
反之,如果
输入格式
输入的第一行包含两个整数
第二行包含
输出格式
输出一行包含
样例 #1
样例输入 #1
1 | 3 3 |
样例输出 #1
1 | 3 2 -1 |
提示
在开始放置宝石之前,体力为
- 将第
个宝石放进第 个盒子,得到 ,体力剩余 。 - 将第
个宝石放进第 个盒子,得到 ,体力剩余 。
最后宝石在盒子中的排列为
对于
对于所有评测用例,
解法
贪心+线段树
我博客里的线段树:https://misaka-xxw.github.io/2025/02/02/segment-tree/
解释
给定
要求:
- 数
可以放在 的位置区间 - 位置
可以放置区间 的数 - 可以有空的位置,相邻位置不能有相同的数。
- 字典序的解释:两个排列方法,对于最靠前的放置了不相等的数的位置,放更大的数的那个字典序更大。没有放数就是-1。如:[5,4,3,…]比[5,4,2,…]大
贪心
- 优先将更大的数放置到更靠前的位置
- 对于相等的数,选更靠前的
- 两个位置不能同时放一样的数
线段树
- 作用:区间
内最大值和次大值的查询和更新 从1遍历到n,查询 区间内的最大值,放在位置 上。 - 如果和上一个答案相同,选次大值。
- 使用了宝石,就要更新线段树
1 |
|