提醒:篇幅可能有点长,为了方便,大家可以直接看目录快速查找想要的内容
1.新生【算法赛】 - 蓝桥云课 (lanqiao.cn)
题面:
思路:上届小桥获得了第14届总冠军,那么这届是第15届,直接输出15就是答案
2.铺地板【算法赛】 - 蓝桥云课 (lanqiao.cn)
题面:
input:
4
7 6
2 2
12 8
1 12
output:
Yes
No
Yes
No
思路:思维/数学
1.对于每一块地板,如果能被凑出来,那么一定是2*3地砖组合出来的,无论2*3地砖怎么放都为6的倍数,故长为n,宽为m的地板,n*m%6==0一定成立
2.这里还要注意一个特判,就是如果长或宽为1(例如n=6,m=1),那么是6的倍数也无法满足要求(不能切割地砖)
Ac_code:java
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int T=sc.nextInt();
while(T-->0){
int n=sc.nextInt(),m=sc.nextInt();
if(n==1||m==1) System.out.println("No");
else if(n*m%6==0) System.out.println("Yes");
else System.out.println("No");
}
}
}
3.摆玩具【算法赛】 - 蓝桥云课 (lanqiao.cn)
题面:
input:
5 2
2 5 7 10 13
output:
8
思路:思维/贪心
简述题意:给一个长度为n的不下降数组,分成k个子数组,使子数组的极差的总和最小
1.对数组中相邻两数的差记为 f[0],f[1],f[2],f[3]....f[n-2],并对其累加记为sum(这里注意数组是不下降的),故f数组中的元素是>=0的。
2.此时可以发现sum就是将长度为n的数组的极差值。
3.但是题目有一个限制条件分成k个子数组,k等于1时,sum就是答案,k>=2时,此时贪心的想让相差大的分开多开一个子数组,以满足极差总和最小
举个栗子:
h数组: 2 5 7 10 13
f数组:3 2 3 3
k等于2时,删除一个最大的数3,有3个3,故有三种情况分子数组的情况都满足条件,
删除第一个3为:子数组分为 [2], [5 7 10 13],极差和为:0+8
删除第二个3 为:子数组分为[2,5,7], [10,13],极差和为:5+3
删除第三个3为:子数组分为[2,5,7,10],[13],极差和为:8+0
4.实现时对f数组排序,用总和减去f中(k-1)个最大的数
Ac_code:C++
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
4.通关【算法赛】 - 蓝桥云课 (lanqiao.cn)
题面:
input:
4 5
0 3 5
1 2 8
1 3 9
3 1 15
output:
3
思路:bfs+堆优化
简述题意:给一个以1为根的有向树和初始的经验,问最多能覆盖的结点为多少个
设与1相连且小于已有经验的结点集合记为S
1.,很容易想到一个暴力做法,就是对所有小于当前经验值的遍历一遍,看是否可以扩展树的大小,没有一个结点可以更新,直接输出答案,有一个结点可以更新,就可以再次进入循环遍历一遍S集合中的所有元素,但是这个方法会tle,故要优化。
2.我们换一个思考方式,把与1相连的结点但是还没有加入到集合S中的集合,记录到一个小根堆中,每次从小根堆中取出最小的闯关所需要经验值,看是否可以加入到集合中,可以加入集合中接着循环判断,不可以直接跳出循环输出答案
Ac_code:C++
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
5.串门【算法赛】 - 蓝桥云课 (lanqiao.cn)
题面:
input:
4
1 2 3
1 3 4
1 4 5
output:
15
思路:dfs求树的直径
简述题意:n个节点,n-1条边,选择一个结点为起点,输出访问所有结点的最小值
1.直接求很难,那么换个思路,每个结点必须遍历一次,那么每条边至少加一次,每条边加一次的总和记为sum,我们的目的就是让一些边遍历两次或者两次以上的可能尽量小,那么找出最长第一条路径max_len(注意是权值最大),让它只遍历一次,就能保证答案最小,那么sum-max_len就是遍历两次的边权值,答案就是sum+sum-max_len。
2.那么这么求sum,max_len呢?sum很好求,直接累加边权值即可,max_len其实是最大的一条路径(树的直径),那么就转化求树的直径即可。
3.求树的直径(最大的一条路径),这里有通解,就是随便找一个点,dfs一遍记录最大路径的值与结点编号,在用第一次记录的结点编号第二次dfs,更新最大的max_len即可。(这里感兴趣证明的可以查树的直径,还有注意一点就是树的直径不能有负权边,不然不能用此方法求解,要数形dp才能求解)
Ac_code:C++
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
6.神奇数【算法赛】 - 蓝桥云课 (lanqiao.cn)
题面:
input:
100
130
output:
5
思路:数位dp
简述题意:求[l,r]中神奇树的个数,神奇数的定义假设有n(n>=2)位数 s1,s2..sn,对数位s1+s2+..+sn-1的总和为sum,sum%sn==0则为神奇数,10<=-l<=r<=1e200
数位初学者入门这里推荐灵神:2376. 统计特殊整数 - 力扣(LeetCode)
1.数位dp的一般求法[1,x]中合法的数,但是我们要求的是[l,r],这里采用前缀和思想pre[r]-pre[l-1]
2.这里采用记忆化搜索,一般用4个参数,本题的4个参数为枚举到了第pos位,前面总和为sum,是否有限制limit,是否有前导0用num
3.枚举到最后一位时,枚举最后一位可以填那些数,满足记录合法数返回即可
Ac_code:C++
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
7.小蓝的疑问【算法赛】 - 蓝桥云课 (lanqiao.cn)
题面:
input:
7 4
2 9 8 7 8 6 4
1 2
1 3
2 4
2 6
3 5
3 7
1 2
1 1
3 1
2 1
output:
8
9
8
7
思路:
简述题意:给你一颗以1为根的有向树,q个询问,对于每个询问x,k,输出x结点为根x记为第0层,输出所有第k层结点的最大值
1,一个简单暴力的方法就是,对每个询问bfs求除第k层结点的值,取max输出即可
TLE_code:C++(超时代码,过了60%的样例)
打蓝桥杯的话,可以获得60%的分,也建议学一学
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
最后一题正解后续更新.....感觉写不出正解了(更改博客时间2023/10/29)
描述有误,或者描述不好理解,欢迎指正
希望对你有用,欢迎关注,点赞,收藏