2025第一周蓝桥杯每日一题
农夫约翰的奶酪块

知识点
解题思路
- 一个
1 * 1 * N
的方块的插入方向有三种:- 沿x轴方向
- 沿y轴方向
- 沿z轴方向
- 所以用三个数组表示某一个面背后的的缺口的数量
- 如果某一个面背后缺口的数量已经达到
n
了,那么说明可以增加一种插入方案
实现代码
#include <bits/stdc++.h>
using namespace std;
const int N= 1100;
int a[N][N], b[N][N], c[N][N];
int n, m;
int main(){
int res = 0;
cin >> n >> m;
for(int i = 0; i < m; i ++){
int x, y, z;
cin >> x >> y >> z;
if(++ a[x][y] == n)
res ++;
if(++ b[x][z] == n)
res ++;
if(++ c[y][z] == n)
res ++;
cout << res << endl;
}
return 0;
}
哞叫时间
知识点
- 枚举
-
printf
和scanf
函数-
printf
函数 -
scanf
函数
-
解题思路
- 根据题意,我们要统计出现次数大于等于
m
次的abb
子串 - 总体思路:将字符串中的每个字符进行修改操作,之后遍历以这个字符分别为最后一个字符,倒数第二个字符,和第一个字符的长度为3的子串
- 时间复杂度:$\Omega(25 \times N)$
- 初始化两个数组:
-
int cnt[a][b]
:记录每个abb
型子串出现的次数 -
int st[N][N]
:记录每个abb
型是否可以作为答案的状态
-
- 建立
update
函数- 输入参数为:
int l, int r, int v
- 对该范围内长度为3的子串的
cnt
数组进行更新,对于满足条件的abb
数组在其cnt
数值上+ v
- 输入参数为:
- 遍历每个字符,将字符修改为除自己其他25个英文字母,对上述的三种子串利用
update
函数进行判断 - 最后遍历
cnt
和st
数组,输出res
和符合条件的abb
型子串
实现代码
#include <bits/stdc++.h>
using namespace std;
const int N = 20200, M = 26;
char s[N];
int n, m;
int cnt[M][M];
int st[M][M];
void update(int l, int r, int v){
l = max(l, 0), r = min(r, n - 1);
for(int i = l; i + 2 <= r; i ++){
char a = s[i], b = s[i + 1], c = s[i + 2];
if(a != b && b == c){
cnt[a][b] += v;
if(cnt[a][b] == m)
st[a][b] = 1;
}
}
}
int main(){
cin >> n >> m >> s;
for(int i = 0; i < n; i ++)
s[i] -= 'a';
// 先统计原串
update(0, n - 1, 1);
// 再统计修改一个字符之后的abb型数量
for(int i = 0; i < n; i ++){
char t = s[i];
update(i - 2, i + 2, -1);
for(int j = 0; j < 26; j ++){
if(j != t){
s[i] = j;
update(i - 2, i + 2, 1);
update(i - 2, i + 2, -1);
}
}
s[i] = t;
update(i - 2, i + 2, 1);
}
int ans = 0;
for(int i = 0; i < 26; i ++)
for(int j = 0; j < 26; j ++)
if(st[i][j])
ans ++;
cout << ans << endl;
for(int i = 0; i < 26; i ++)
for(int j = 0; j < 26; j ++)
if(st[i][j])
printf("%c%c%c\n", i + 'a', j + 'a', j + 'a');
return 0;
}
蛋糕游戏

知识点
- 求前缀和
解题思路
- 我们设定贝茜和埃尔茜分别为
A
和B
- 最后一步一定是由
A
来完成的,因为1个蛋糕是奇数,只能通过两个蛋糕合并为一个蛋糕,然后吃掉 - 所以,我们知道,在理想情况下(
B
不会吃掉A
合并的蛋糕)除了A
最开始合并吃掉的2个蛋糕,其余时间都是B
吃一个A
吃一个成对出现,所以A
会比B
多吃两个蛋糕 - 可得:
A
吃掉的蛋糕数为$\frac{N}{2} + 1$,B
吃掉的蛋糕数为$\frac{N}{2} - 1$

- 如果两个大括号内数的和等于$\frac{N}{2} - 1$的话,那么
B
是一定可以吃掉的- 因为,在理想情况下,
B
可以吃掉$\frac{N}{2} - 1$个蛋糕,倘若其中一个蛋糕被A
合并了,那么B
可以尽早完成吃掉$\frac{N}{2} - 1$个蛋糕的任务,并最终可能吃$\geq \frac{N}{2} - 1$个蛋糕
- 因为,在理想情况下,
- 对于
B
吃的蛋糕,我们将从两边挑选最大的蛋糕给B
吃。给定中间序列$\frac{N}{2} + 1$个蛋糕,使用$S_{min}$来表示这个$\frac{N}{2} + 1$个蛋糕大小和的最小值。综上,B
吃的蛋糕可以表示为:\(B \geq T - S_{min}\) - 接下俩继续探究
A
能否吃$\frac{N}{2} + 1$个蛋糕

- 在游戏开始时,我们假定
A
首先吃掉中间的两个蛋糕,随后蛋糕序列的样式变为上述图片中所显示的。 - 在接下来中,
B
吃掉一个左右任一序列中一个蛋糕,A
随即吃掉另一序列(右左)中的一个蛋糕。这样的吃法可以保证A
吃掉$\frac{N}{2} - 1$个蛋糕。 - 最后,加上最开始吃掉的2个蛋糕,
A
一共吃掉了$\frac{N}{2} + 1$个蛋糕 - 继续分析,不论
B
怎么选择,A
一定可以吃掉$\frac{N}{2} + 1$个蛋糕,并且这些蛋糕大小加和最小,即为$S_{min}$。 - 综上,我们构造出了一种策略,使得
A
可以吃$\frac{N}{2} + 1$个蛋糕,并且大小加和至少为$S_{min}$。所以,B
吃的蛋糕又可以表示为:\(B \leq T - S_{min}\)
实现代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 5e5 + 100;
int n;
LL s[N];
int main(){
int T;
cin >> T;
// 刺挠
while(T --){
cin >> n;
LL a = 1e15;
int l = n / 2 + 1;
for(int i = 1; i <= n; i ++){
int x;
cin >> x;
s[i] = s[i - 1] + x;
if(i >= l)
a = min(a, s[i] - s[i - l]);
}
cout << a << " " << s[n] - a << endl;
}
return 0;
}
Enjoy Reading This Article?
Here are some more articles you might like to read next: