前言
本人参加第十六届蓝桥杯,参赛之前刷了这套真题,整体下来难度适中,完全可以用暴力解决。
1.报数游戏
一般第一道题手算即可得出答案。
题目描述:
小蓝和朋友们在玩一个报数游戏。由于今年是 20242024 年,他们决定要从小到大轮流报出是 2020 或 2424 倍数的正整数。前
1010
个被报出的数是:20,24,40,48,60,72,80,96,100,12020,24,40,48,60,72,80,96,100,120。请问第
202420242024202420242024 个被报出的数是多少? 答案提交这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
根据题意得,该数列每个数是由20或24的倍数交替,从此可以发现出规律,当个数为偶数时是24的倍数,是奇数时是20的倍数,202420242024202420242024 是偶数,规律公式为(n/2 * 24),即可直接得出答案。
2.类斐波那契循环数
题目描述
对于一个有 nn 位的十进制数
N=d1d2d3…dnN={d}{1}{d}{2}{d}{3}\ldots{d}{n}N=d1d2d3…dn,可以生成一个类斐波那契数列SS,数列
SS 的前 nn 个数为:{S1=d1,S2=d2,S3=d3,…,Sn=dn}
\left{{{S}{1}={d}{1},{S}{2}={d}{2},{S}{3}={d}{3},\ldots,{S}{n}={d}{n}}\right}
{S1=d1,S2=d2,S3=d3,…,Sn=dn}数列 SS 的第 k(k>n)k\left({k>n}\right)k(k>n) 个数为:
i=k−nk−1Si \mathop{\sum}\limits_{{i=k-n}}^{{k-1}}{S}_{i} i=k−n∑k−1Si
如果这个数 NN 会出现在对应的类斐波那契数列 SS 中,那么 NN 就是一个类斐波那契循环数。
例如对于 197197,对应的数列 SS 为:
{1,9,7,17,33,57,107,197,…} {1,9,7,17,33,57,107,197,…}
197197 出现在 SS 中,所以 197197 是一个类斐波那契循环数。
请问在 00 至 107107 中,最大的类斐波那契循环数是多少? 答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
因为该题让求最大值,所以可以直接采取暴力的方法倒叙遍历,先把该数字转换为字符串,从而得到位数,然后对该位数进行不断累加,从而求出答案
package moni15;
import java.util.ArrayList;
import java.util.List;
//类斐波那契循环数
public class Main2 {
public static void main(String[] args) {
int a = 10000000;
for(int i = a;i >= 0;i--) {
if(isF(i)) {
System.out.println(i);
break;
}
}
}
public static boolean isF(int num) {
String str = Integer.toString(num);
int len = str.length();
List<Integer> list = new ArrayList<Integer>();
for(int i = 0;i < len;i++) {
list.add(str.charAt(i) - '0');
}
while(true){
int sum = 0;
for(int i = list.size() - len;i < list.size();i++) {
sum = sum + list.get(i);
}
list.add(sum);
if(sum > num) {
return false;
}
if(sum == num) {
return true;
}
}
}
}
分布式队列
题目描述
小蓝最近学习了一种神奇的队列: 分布式队列。简单来说,分布式队列包含 NN 个节点(编号为 0 至 N−1N−1,其中 0
号为主节点),其中只有一个主节点,其余为副节点。主/副节点中都各自维护着一个队列,当往分布式队列中添加元素时,都是由主节点完成的(每次都会添加元素到主节点对应的队列的尾部);副节点只负责同步主节点中的队列。可以认为主/副节点中的队列是一个长度无限的一维数组,下标为
0,1,2,3…0,1,2,3…,同时副节点中的元素的同步顺序和主节点中的元素添加顺序保持一致。由于副本的同步速度各异,因此为了保障数据的一致性,元素添加到主节点后,需要同步到所有的副节点后,才具有可见性。
给出一个分布式队列的运行状态,所有的操作都按输入顺序执行。你需要回答在某个时刻,队列中有多少个元素具有可见性。 输入格式
第一行包含一个整数 NN,表示节点个数。
接下来包含多行输入,每一行包含一个操作,操作类型共有以下三种: addadd、syncsync 和
queryquery,各自的输入格式如下:addelementaddelement: 表示这是一个添加操作,将元素 elementelement 添加到队列中; syncfolloweridsyncfollowerid: 表示这是一个同步操作,followeridfollowerid 号副节点会从主节点中同步下一个自己缺失的元素; queryquery: 查询操作,询问当前分布式队列中有多少个元素具有可见性。
该题目也属于基础题目,采用模拟的形式,这个题有一个小技巧在于查询操作只显示元素同步个数,所以添加add操作时,只需要在每次add时count+1,而不需要注意具体添加的是什么值。还有一个注意点是他的测试用例,1≤N≤10,所以直接定义大小为10的数组存储数量即可
package moni15;
//1:无需package
//2: 类名必须Main, 不可修改
//分布式队列
import java.util.Scanner;
public class Main3 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int[] count = new int[n];
while(scanner.hasNext()) {
String str = scanner.next();
if(str.equals("add")) {
count[0]++;
continue;
}
if(str.equals("sync")) {
int num = scanner.nextInt();
//同步操作时,被同步的节点数量必须小于主节点
if(count[0] > count[num]) {
count[num]++;
continue;
}else {
continue;
}
}
if(str.equals("query")) {
int m = Integer.MAX_VALUE;
for(int i = 0; i < n;i++) {
//可见数量即最小的元素
m = Math.min(m,count[i]);
}
System.out.println(m);
}
}
scanner.close();
}
}
4.食堂
题目描述:
S 学校里一共有 a2a2 个两人寝、a3a3 个三人寝,a4a4 个四人寝,而食堂里有 b4b4 个四人桌和 b6b6
个六人桌。学校想要安排学生们在食堂用餐,并且满足每个寝室里的同学都在同一桌就坐,请问这个食堂最多同时满足多少同学用餐? 输入格式采用多组数据输入。
输入共 q+1q+1 行。
第一行为一个正整数 qq 表示数据组数。
后面 qq 行,每行五个非负整数 a2,a3,a4,b4,b6a2,a3,a4,b4,b6 表示一组数据。 输出格式
输出共 qq 行,每行一个整数表示对应输入数据的答案。 样例输入
2 3 0 1 0 1 0 2 2 1 1 [copy]
样例输出
6 10
该题目大概一看,就是贪心算法,其实用贪心的思想,暴力的做法,这道题就容易理解了
优先坐满6人桌,再坐满4人桌。
先考虑配满情况 3+3 ,4 + 2, 2 + 2 + 2, 4,2+2
**再考虑不满配的情况 3 + 2 ,4装6,3装4 2装6 2装4 **
package moni15;
import java.util.Scanner;
//食堂
//贪心加暴力
public class Main4 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
//在此输入您的代码...
int q = scanner.nextInt();
for(int i = 0;i < q;i++) {
int total = 0;
int a2 = scanner.nextInt();
int a3 = scanner.nextInt();
int a4 = scanner.nextInt();
int b4 = scanner.nextInt();
int b6 = scanner.nextInt();
//先考虑能配对情况
//先考虑六人桌
//再考虑四人桌
//3+3
while(a3 >= 2 && b6 >= 1) {
a3 = a3 - 2;
b6--;
total = total + 6;
}
//4+2
while(a4 >= 1 && a2 >= 1 && b6 >= 1) {
a4--;
a2--;
b6--;
total = total + 6;
}
//1个4
while(a4 >= 1 && b4 >= 1) {
a4--;
b4--;
total = total + 4;
}
//3个2
while(a2 >= 3 && b6 >= 1) {
a2 = a2 - 3;
b6--;
total = total + 6;
}
//2个2
while(a2 >= 2 && b4 >= 1) {
a2 = a2 - 2;
b4--;
total = total + 4;
}
//匹配不配对的情况
//1个3 一个2
while(a3 >= 1 && a2 >= 1 && b6 >= 1) {
a3--;
a2--;
b6--;
total = total + 5;
}
//一个4
while(a4 >= 1 && b6 >= 1) {
a4--;
b6--;
total = total + 4;
}
//一个3
while(a3 >= 1 && b4 >= 1) {
a3--;
b4--;
total = total + 3;
}
//一个3
while(a3 >= 1 && b6 >= 1) {
a3--;
b6--;
total = total + 3;
}
//一个2
while(a2 >= 1 && b6 >= 1) {
a2--;
b6--;
total = total + 2;
}
//一个2
while(a2 >= 1 && b4 >= 1) {
a2--;
b4--;
total = total + 2;
}
System.out.println(total);
}
scanner.close();
}
}
5.最优分组
题目描述
小蓝开了一家宠物店,最近有一种 XX 病毒在动物之间进行传染,小蓝为了以防万一打算购买测试剂对自己的宠物进行病毒感染测试。
为了减少使用的测试剂数目,小蓝想到了一个好方法:将 NN 个宠物平均分为若干组,使得每组恰好有 KK
只宠物,这样对同一组的宠物进行采样并混合后用一个试剂进行检测,如果测试结果为阴性则说明组内宠物都未感染 XX
病毒;如果是阳性的话则需要对组内所有 KK 只宠物单独检测,需要再消耗 KK 支测试剂(当 K=1K=1
时,就没必要再次进行单独检测了,因为组内只有一只宠物,一次检测便能确认答案)。现在我们已知小蓝的宠物被感染的概率为 pp,请问 KK 应该取值为多少才能使得期望的测试剂的消耗数目最少?如果有多个答案输出最小的 KK。
输入格式第一行,一个整数 NN 。
第二行,一个浮点数 pp 。 输出格式
输出一行,一个整数 KK 表示答案。 样例输入
1000
0.05 [copy]样例输出
5
这题主要用的数学期望解决问题,至少一个人被感染的概率为p,那么没有被感染的则为1-p,又因为每组K个人,所以每人被感染的概率为(1-p)的k次方,因为一组k个人 再 乘 k 又因为n / k 组 所以再乘
package moni15;
import java.util.Scanner;
//最优分组
public class Main5 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
//获取宠物个数
int n = scanner.nextInt();
//获取被感染的概率
double possible = scanner.nextDouble();
//最优试剂数
int best = 1;
//初始化最小期望
double minExpect = Double.MAX_VALUE;
//暴力枚举
for(int i = 1;i <= n;i++) {
//说明可以分组
if(n % i == 0) {
//试剂的期望值
//因为至少有一只被感染的概率为p,不好求
//所以里取反
double expect = (1- Math.pow((1 - possible),i)) * i * (n / i) + n / i;
if(expect < minExpect) {
minExpect = expect;
best = i;
}
}
}
System.out.println(best);
scanner.close();
}
}
6.星际旅行
题目描述
小明国庆节准备去某星系进行星际旅行,这个星系里一共有 nn 个星球,其中布置了 mm 道双向传送门,第 ii 道传送门可以连接
ai,biai,bi 两颗星球(ai≠biai=bi 且任意两颗星球之间最多只有一个传送门)。他看中了一款 “旅游盲盒”,一共有 QQ 个盲盒,第 ii 个盲盒里的旅行方案规定了旅行的起始星球 xixi 和最多可以使用传送门的次数
yiyi。只要从起始星球出发,使用传送门不超过规定次数能到达的所有星球都可以去旅行。小明关心在每个方案中有多少个星球可以旅行到。小明只能在这些盲盒里随机选一个购买,他想知道能旅行到的不同星球的数量的期望是多少。 输入格式
输入共 m+Q+1m+Q+1 行。
第一行为三个正整数 n,m,Qn,m,Q 。
后面 mm 行,每行两个正整数 ai,biai,bi 。
后面 QQ 行,每行两个整数 xi,yixi,yi 。 输出格式
输出共一行,一个浮点数(四舍五入保留两位小数)。 样例输入
3 2 3 1 2 2 3 2 1 2 0 1 1 [copy]
样例输出
2.00
该题考查的是bfs广度优先算法。
package moni15;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Scanner;
public class Main6{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
//获取总星球数量
int n = scanner.nextInt();
//获取传送门个数
int m = scanner.nextInt();
//获取盲盒数量
int q = scanner.nextInt();
//用邻接表构造图
List<List<Integer>> graph = new ArrayList<List<Integer>>();
for(int i = 0;i <= n;i++) {
graph.add(new ArrayList<Integer>());
}
//在图中处理传送门
for(int i = 0;i < m;i++) {
int a = scanner.nextInt();
int b = scanner.nextInt();
graph.get(a).add(b);
graph.get(b).add(a);
}
double total = 0;
//处理盲盒
for(int i = 0;i < q;i++) {
int start = scanner.nextInt();
int step = scanner.nextInt();
total = total + bfs(graph,start,step);
}
//计算期望
double expect = total / q;
//四舍五入,保留两位小数
System.out.printf("%.2f",expect);
scanner.close();
}
public static int bfs(List<List<Integer>> graph,int start,int step) {
//定义数组,记录拜访过的节点
boolean[] visited = new boolean[graph.size()];
//定义队列,里面存俩元素记录当前节点和步数
Queue<int[]> queue = new LinkedList<int[]>();
//初始化一条记录
queue.offer(new int[] {start,0});
//当前节点被拜访
visited[start] = true;
//记录总数
int total = 0;
//bfs
while(!queue.isEmpty()) {
//弹出一个
int[] current = queue.poll();
//取出节点和步数
int node = current[0];
int steps = current[1];
total++;
//如果步数小于限制步数,开始遍历邻居节点
if(steps < step) {
for(int neibor : graph.get(node)) {
if(!visited[neibor]) {
queue.offer(new int[] {neibor,steps + 1});
visited[neibor] = true;
}
}
}
}
return total;
}
}
其中用邻接表的方法构造图,用队列来存储当前元素和走的步数
7.LIST
该题应该也是大模拟的做法,没做出来
8.拼十字
在 LQLQ 国神秘的古老森林,有一座被称为 “拼十字” 的神秘遗迹。据传,“拼十字”
是由古代文明建造的,它是一个巨大的石头结构,由两个巨大的矩形交叉叠放在一起,形成了一个庄严而神秘的十字形状。这个遗迹被认为是连接人类和神灵之间的通道,拥有神秘的力量和能量。
图片描述现在给出 NN 个矩形,其中第 ii 个矩形的长度和宽度分别问 li,wili,wi,并且矩形颜色 cici 为红 (0)/(0)/
黄 (1)/(1)/ 蓝 (2)(2) 中的一种。现在小蓝想知道在这 NN 个矩形中有多少对矩形可以 “拼十字”?两个矩形可以 “拼十字” 的充要条件是:
两个矩形的颜色不同; 矩形 11 的长度严格大于矩形 22 的长度并且矩形 11 的宽度严格小于矩形 22 的宽度。
注意,矩形长度和宽度属性是固定的,是不可以通过旋转矩形而发生转变的。
这题我觉得非常简单,但是坑的是放到最后一题的位置,直接用暴力循环可以拿九分,但会超时,总比没分要强
package moni15;
import java.util.Scanner;
//拼十字
public class Main8 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int[][] arr = new int[n][3];
//给二维数组赋值
for(int i = 0;i < n;i++) {
arr[i][0] = scanner.nextInt();
arr[i][1] = scanner.nextInt();
arr[i][2] = scanner.nextInt();
}
//暴力轻松求解
int count = 0;
for(int i = 0;i < n;i++){
for(int j = 0;j < n;j++) {
if(i != j && arr[i][2] != arr[j][2] && arr[i][0] > arr[j][0] && arr[i][1] < arr[j][1]) {
count++;
}
}
}
System.out.println(count % 1000000007);
}
}
总结
其实该套真题核心思想不难,但是分析题意较难,不管咋说,遇到啥题先用暴力,能通过多少测评用例通过多少。马上开始16届比赛,大佬们有啥备赛建议没?