目录
- 十五届蓝桥杯省赛Java B组
- 第一题:报数
- 第二题:类斐波那契数
- 第三题:分布式队列
- 第四题:食堂
- 第五题:最优分组
- 第六题:星际旅行
- 第七题:LITS游戏
- 第八题:拼十字
十五届蓝桥杯省赛Java B组
第一题:报数
📚
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
long result = 202420242024L / 2 * 24;
//思想:奇数位都是20的倍数,偶数位都是24的倍数,可知202420242024的一半为奇数,第202420242024位除以2乘以24就能得到答案
//举个例子:第4位是第2个24的倍数,第6位是第3个24的倍数......那第202420242024位就是第101210121012个24的倍数,
//所以答案就是:202420242024 / 2 * 24
System.out.println(result);
scan.close();
}
}
主要是找规律,硬解很难解出来。
第二题:类斐波那契数
因为是找最大,所以逆序遍历会快点,第一个符合条件的数就是答案。
我的暴力解法,比赛不会那只能放在一边让他跑了,按道理来说是能跑出来的。
package test;
import javax.swing.*;
import java.util.*;
public class Main {
static int N = 10000000;
static int[] a = new int[20];
static long[] b = new long[N];
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
for (int i = N; i >= 197; i--) {
if(check(i)){
System.out.println(i);
break;
}else {
System.out.println(i);
}
}
}
// 检查是否是 类斐波那契 循环数
static boolean check(int x) { // num是位数
String str = x + "";
int len = str.length();
for (int i = 0; i < len; i++) {
b[i + 1] = str.charAt(i) - '0';
}
for (int i = len + 1; b[i - 1] < x; i++) {
b[i] = dfs(i);
// System.out.println(" i:"+i);
// System.out.println(b[i]);
if( b[i] == x) return true;
if( b[i] > x) return false;
}
return false;
}
// dfs递归
static long dfs(int x){
if(x == 1) return b[1];
if(x == 2) return b[2];
if(x == 3) return b[3];
return dfs(x-1) + dfs(x - 2) + dfs(x - 3);
}
}
📚法一
import java.util.*;
public class Main {
static int N = 10000000;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
for (int i = N; i >= 197; i--) {
if(check(i)){
System.out.println(i);
break;
}
}
}
static boolean check(int x){
String str = x + "";
// 获取位数
int len = str.length();
// 数组大小为len就够用了
int[] dp = new int[len];
// 将 x 每一位都拆出来
for (int i = 0; i < len; i++) {
dp[i] = str.charAt(i) - '0';
}
// 数组求和
int sum = 0;
for (int i = len; sum < x ; i++) {
sum = Arrays.stream(dp).sum(); // 数组求和,注意语法
dp[i % len] = sum; // 后面用不到的下标元素 进行替换
}
return sum == x; // 两种结果:=x返回true,>x返回false
}
}
每次求和其实只用到len个元素,所以可以对后续用不到的元素进行替换。
📚法二:
import java.util.*;
public class Main {
static int N = 10000000;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
for (int i = N; i >= 197; i--) {
if(check(i)){
System.out.println(i); // 7913837
break;
}
}
}
// 检查是否是 类斐波那契 循环数
static boolean check(int x) { // num是位数
String str = x + "";
int len = str.length();
int sum = 0;
ArrayList<Integer> a = new ArrayList<>();
for (int i = 0; i < len; i++) {
int num = str.charAt(i) - '0';
a.add(num); // [1,9,7]
sum += num;
}
//上面的这个循环究竟是在干什么事情:下面的这个以1234为例子说明,方便理解
//列表 a 存储了整数 1234 的各个数位数字 [1, 2, 3, 4],
// 变量 sum 的值为 10,即整数 1234 各个数位数字的总和。
a.add(sum);
// 此时变成了[1, 2, 3, 4,10]
if(sum == x) return true;
while(sum < x){
//乘以2减去这个里面的第一个元素就是这个类斐波那契数列的规律,避免使用纯粹的数学方法计算
sum = sum * 2 - a.get(0);
a.remove(0);
a.add(sum);
if(sum == x) return true;
}
return false;
}
}
思想:要求
第k+1位以后的数
只需将k
乘以2减去这个里面的第一个元素就是这个类斐波那契数列的规律,避免使用纯粹的数学方法计算。
第三题:分布式队列
👇写成这样有9个样例过不了,因为没有考虑副队列不超过主队列。
import java.util.*;
public class Main {
static int N = 2010;
static int INF = 100005;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] a = new int[n];
while(sc.hasNext()){
String str = sc.next();
if(str.equals("add")){
int num = sc.nextInt();
a[0] ++;
}else if (str.equals("sync")){
int num = sc.nextInt();
a[num] ++;
} else if (str.equals("query")) {
int ans = INF;
for (int i = 0; i < n; i++) {
ans = Math.min(ans,a[i]);
}
System.out.println(ans);
}
}
}
}
📚分布式队列
第四题:食堂
import java.util.*;
public class Main {
static int N = 2010;
static int INF = 100005;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int q = sc.nextInt();
while(q-->0) {
int a2 = sc.nextInt();
int a3 = sc.nextInt();
int a4 = sc.nextInt();
int b4 = sc.nextInt();
int b6 = sc.nextInt();
int sum = 0;
// 满座 匹配4人寝坐4人桌
while(a4 != 0 && b4 != 0){
a4 --;b4 --;
sum += 4;
}
// 满座 匹配2x2人寝坐4人桌
while(a2 != 0 && b4 != 0){
a2 = a2 - 2;b4 --;
sum += 4;
}
// 满座 匹配2+4人寝坐6人桌
while(a2 != 0 && a4 != 0 && b6 != 0){
a2 --;a4 --;b6 --;
sum += 6;
}
// 满座 匹配2x3人寝坐6人桌
while(a3 != 0 && b6 != 0){
a3 = a3 - 2;b6--;
sum += 6;
}
// 满座 匹配3x2人寝坐6人桌
while(a2 != 0 && b6 != 0){
a2 = a2 - 3;b6 --;
sum += 6;
}
// 空1座 匹配3人寝坐4人桌
while(a3 != 0 && b4 != 0){
a3--;b4--;
sum += 3;
}
// 空1座 匹配3+2人寝坐6人桌
while(a3 != 0 && a2 != 0 && b6 != 0){
a3--;a2--;b6--;
sum += 5;
}
// 空2座 匹配2人寝坐4人桌
while(a2 != 0 && b4 != 0){
a2--;b4--;
sum += 2;
}
// 空2座 匹配4人寝坐6人桌
while(a4 != 0 && b6 != 0){
a4--;b6--;
sum += 4;
}
// 空2座 匹配2x2人寝坐6人桌
while(a2 != 0 && b6 != 0){
a2 = a2 - 2;b6--;
sum += 4;
}
// 空3座 匹配3人寝坐6人桌
while(a3 != 0 && b6 != 0){
a3--;b6--;
sum += 3;
}
// 空4座 匹配2人寝坐6人桌
while(a2 != 0 && b6 != 0){
a2--;b6--;
sum += 2;
}
System.out.println(sum);
}
}
}
☝️以上写法还有点小错误,
b!=0
是可以的,但是a不能写成a!=0
。例如满座 匹配2x2人寝坐4人桌
,要确保a2宿舍有两个,所以不能写成a2!=0
,要写成a2 >= 2
。
📚
import java.util.*;
public class Main {
static int N = 2010;
static int INF = 100005;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int q = sc.nextInt();
while(q-->0) {
int a2 = sc.nextInt();
int a3 = sc.nextInt();
int a4 = sc.nextInt();
int b4 = sc.nextInt();
int b6 = sc.nextInt();
int sum = 0;
// 满座 匹配4人寝坐4人桌
while(a4 >= 1 && b4 > 0){
a4 --;b4 --;
sum += 4;
}
// 满座 匹配2x2人寝坐4人桌
while(a2 >= 2 && b4 > 0){
a2 = a2 - 2;b4 --;
sum += 4;
}
// 满座 匹配2+4人寝坐6人桌
while(a2 >= 1 && a4 >= 1 && b6 > 0){
a2 --;a4 --;b6 --;
sum += 6;
}
// 满座 匹配2x3人寝坐6人桌
while(a3 >= 2 && b6 > 0){
a3 = a3 - 2;b6--;
sum += 6;
}
// 满座 匹配3x2人寝坐6人桌
while(a2 >= 3 && b6 > 0){
a2 = a2 - 3;b6 --;
sum += 6;
}
// 空1座 匹配3人寝坐4人桌
while(a3 >= 1 && b4 > 0){
a3--;b4--;
sum += 3;
}
// 空1座 匹配3+2人寝坐6人桌
while(a3 >= 1 && a2 >= 1 && b6 > 0){
a3--;a2--;b6--;
sum += 5;
}
// 空2座 匹配2人寝坐4人桌
while(a2 >= 1 && b4 > 0){
a2--;b4--;
sum += 2;
}
// 空2座 匹配4人寝坐6人桌
while(a4 >= 1 && b6 > 0){
a4--;b6--;
sum += 4;
}
// 空2座 匹配2x2人寝坐6人桌
while(a2 >= 2 && b6 > 0){
a2 = a2 - 2;b6--;
sum += 4;
}
// 空3座 匹配3人寝坐6人桌
while(a3 >= 1 && b6 > 0){
a3--;b6--;
sum += 3;
}
// 空4座 匹配2人寝坐6人桌
while(a2 >= 1 && b6 > 0){
a2--;b6--;
sum += 2;
}
System.out.println(sum);
}
}
}
🍎
能想出来贪心策略就不难。想不出来可以试着骗分👇
if(sum1 > sum2){
sout(sum2)
}else if(sum1 <= sum2){
sout(sum1)
}
第五题:最优分组
📚最优分组
思路是:要求 使用试剂最少 情况下的分组策略k -> 最少试剂是x -> 对每组k个宠物消耗试剂的情况分类 -> 求出期望公式 -> 特殊情况 k=1
关键是要求出期望公式,这题就好做了。另外还要想到k=1这个特殊情况,进行特判。所以这题难度挺大的。
第六题:星际旅行
📚星际旅行
第七题:LITS游戏
第八题:拼十字
⭐️考点总结:
1.数学+1
2.暴力 构造 枚举 +1
3.模拟+1
4.贪心+1
5.数学 概率 期望 +1
6.Dijkstra 最短路问题 期望 +1
7.
8.