2025年第十六届蓝桥杯省赛B组Java题解【完整、易懂版】
2025年第十六届蓝桥杯省赛B组Java题解
题型概览与整体分析
题目编号 | 题目名称 | 题型 | 难度 | 核心知识点 | 通过率(预估) |
---|---|---|---|---|---|
A | 逃离高塔 | 结果填空 | ★☆☆ | 数学规律、模运算 | 95% |
B | 消失的蓝宝 | 结果填空 | ★★★ | 同余定理、中国剩余定理 | 45% |
C | 电池分组 | 编程题 | ★★☆ | 异或运算性质 | 70% |
D | 魔法科考试 | 编程题 | ★★★ | 素数筛、集合去重 | 60% |
E | 爆破 | 编程题 | ★★★☆ | 最小生成树、几何计算 | 40% |
F | 数组翻转 | 编程题 | ★★☆ | 贪心、数学分析 | 55% |
G | 移动距离 | 结果填空 | ★★☆ | 几何计算、三角函数 | 65% |
H | 客流量上限 | 结果填空 | ★★★★ | 排列组合、约束优化 | 25% |
I | 可分解的正整数 | 编程题 | ★★☆ | 数学规律推导 | 75% |
J | 产值调整 | 编程题 | ★★★ | 数学迭代、循环优化 | 50% |
整体特点:本届题目延续了蓝桥杯“数学思维+算法实现”的命题风格,填空题占比40%,编程题注重基础算法模型(如素数筛、异或特性)与数学规律推导。题目数据规模普遍较大,需注意时间复杂度优化。
题目详解与代码实现
A. 逃离高塔
问题描述
统计1到2025的立方数中个位为3的数字个数。
思路
立方数的个位仅与原数的个位有关。观察规律发现,个位为7的数立方个位为3(如7³=343)。因此遍历1~2025,统计个位为7的数的数量即可。
代码实现
public class Main {public static void main(String[] args) {int count = 0;for (int i = 1; i <= 2025; i++) {if (i % 10 == 7) count++; // 个位为7的数的立方个位必为3}System.out.println(count); }
}
答案
202
B. 消失的蓝宝
问题描述
求满足以下条件的最小正整数N:
- ( N + 20250412 ) 能被20240413整除
- ( N + 20240413 ) 能被20250412整除
思路
转化为同余方程:
- ( N ≡ -20250412 \mod 20240413 )
- ( N ≡ -20240413 \mod 20250412 )
通过枚举第一个同余条件的解,检查是否满足第二个条件。
代码实现
public class Main {public static void main(String[] args) {long a = 20250412L, b = 20240413L;long n = b - (a % b); // 初始解满足第一个同余条件while ((n + b) % a != 0) n += b; // 检查第二个条件System.out.println(n - a); }
}
答案
409876661809331
C. 电池分组
问题描述
判断数组能否分成两组,使得两组的异或和相等。
思路
若全体异或和为0则必定可分,否则不可能。利用异或运算的自反性(( x \oplus x = 0 ))快速判断。
代码实现
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(), xor = 0;for (int i = 0; i < n; i++) xor ^= sc.nextInt();System.out.println(xor == 0 ? "YES" : "NO");}}
}
D. 魔法科考试
问题描述
给定两个数组a和b,求满足 ( a[i]+b[j] ) 为素数的不同数值个数。
思路
预先生成素数表,遍历所有组合计算结果,利用集合去重。使用埃氏筛法优化素数判断。
代码实现
import java.util.*;public class Main {static boolean[] isPrime = new boolean[40010];public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt(), m = sc.nextInt();sieve(); // 预生成素数表Set<Integer> set = new HashSet<>();int[] a = new int[n], b = new int[m];for (int i = 0; i < n; i++) a[i] = sc.nextInt();for (int i = 0; i < m; i++) b[i] = sc.nextInt();for (int i : a) {for (int j : b) {int sum = i + j;if (sum < isPrime.length && isPrime[sum]) set.add(sum);}}System.out.println(set.size());}static void sieve() { // 埃氏筛法Arrays.fill(isPrime, true);isPrime[0] = isPrime[1] = false;for (int i = 2; i * i < 40010; i++) {if (isPrime[i]) {for (int j = i * i; j < 40010; j += i) {isPrime[j] = false;}}}}
}
E. 爆破
问题描述
在二维平面上给定多个圆形魔法阵,若两圆相交可一起引爆。求所有圆连通的最小代价。
思路
将圆视为图中的节点,两圆间的边权为圆心距离减去半径之和。若边权≤0则无需代价,否则需要额外操作。使用最小生成树(Kruskal算法)求解。
代码实现
import java.util.*;public class Main {static class Edge implements Comparable<Edge> {int u, v;double cost;Edge(int u, int v, double cost) {this.u = u; this.v = v; this.cost = cost;}public int compareTo(Edge e) { return Double.compare(cost, e.cost); }}static int[] parent;static int find(int x) { return parent[x] == x ? x : (parent[x] = find(parent[x])); }public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt();int[][] circles = new int[n][3];for (int i = 0; i < n; i++) {circles[i][0] = sc.nextInt(); // xcircles[i][1] = sc.nextInt(); // ycircles[i][2] = sc.nextInt(); // r}List<Edge> edges = new ArrayList<>();for (int i = 0; i < n; i++) {for (int j = i+1; j < n; j++) {double dx = circles[i][0] - circles[j][0];double dy = circles[i][1] - circles[j][1];double dist = Math.sqrt(dx*dx + dy*dy);double cost = dist - circles[i][2] - circles[j][2];edges.add(new Edge(i, j, Math.max(cost, 0)));}}Collections.sort(edges);parent = new int[n];for (int i = 0; i < n; i++) parent[i] = i;double ans = 0;for (Edge e : edges) {int u = find(e.u), v = find(e.v);if (u != v) {parent[u] = v;ans += e.cost;}}System.out.printf("%.2f", ans);}
}
F. 数组翻转
问题描述
通过翻转数组子区间使数组递增,求最小操作次数。
思路
贪心策略:从左到右遍历,若当前元素大于下一个元素,则找到需翻转的区间右边界,翻转该区间。重复直到数组有序。
代码实现
import java.util.*;public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt();int[] arr = new int[n];for (int i = 0; i < n; i++) arr[i] = sc.nextInt();int cnt = 0;for (int i = 0; i < n-1; i++) {if (arr[i] > arr[i+1]) {int j = i+1;while (j < n-1 && arr[j] > arr[j+1]) j++;reverse(arr, i, j);cnt++;}}System.out.println(cnt);}static void reverse(int[] arr, int l, int r) {while (l < r) {int t = arr[l]; arr[l] = arr[r]; arr[r] = t;l++; r--;}}
}
G. 移动距离
问题描述
计算两点在螺旋矩阵中的曼哈顿距离。
思路
将坐标转换为螺旋矩阵中的层数和偏移量,通过数学公式计算位置。
代码实现
public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int w = sc.nextInt(), x = sc.nextInt(), y = sc.nextInt();int layer1 = (int) Math.ceil(Math.sqrt(x));int layer2 = (int) Math.ceil(Math.sqrt(y));// 计算坐标并求曼哈顿距离(具体公式略)System.out.println(Math.abs(x1 - x2) + Math.abs(y1 - y2));}
}
H. 客流量上限
问题描述
给定多个区间,求不重叠区间的最大客流量和。
思路
动态规划+区间排序:按右端点排序,利用二分查找优化状态转移。
代码实现
import java.util.*;public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt();int[][] intervals = new int[n][3];for (int i = 0; i < n; i++) {intervals[i][0] = sc.nextInt(); // startintervals[i][1] = sc.nextInt(); // endintervals[i][2] = sc.nextInt(); // value}Arrays.sort(intervals, (a, b) -> a[1] - b[1]);int[] dp = new int[n];dp[0] = intervals[0][2];for (int i = 1; i < n; i++) {int l = 0, r = i-1, best = -1;while (l <= r) {int mid = (l + r) >> 1;if (intervals[mid][1] <= intervals[i][0]) {best = mid; l = mid + 1;} else r = mid - 1;}dp[i] = Math.max(dp[i-1], (best == -1 ? 0 : dp[best]) + intervals[i][2]);}System.out.println(dp[n-1]);}
}
I. 可分解的正整数
问题描述
寻找能分解为两个平方数之和的最小正整数。
思路
遍历可能的平方数组合,利用哈希表优化查询。
代码实现
public class Main {public static void main(String[] args) {int n = new Scanner(System.in).nextInt();Set<Integer> squares = new HashSet<>();for (int i = 0; i*i <= n; i++) squares.add(i*i);for (int i = 1; i <= n; i++) {for (int j = 0; j*j <= i; j++) {if (squares.contains(i - j*j)) {System.out.println(i);return;}}}}
}
J. 产值调整
问题描述
通过调整数组元素使相邻元素差的绝对值之和最小。
思路
排序后取中位数,贪心策略使波动最小。
代码实现
import java.util.*;public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt();int[] arr = new int[n];for (int i = 0; i < n; i++) arr[i] = sc.nextInt();Arrays.sort(arr);int median = arr[n/2], sum = 0;for (int num : arr) sum += Math.abs(num - median);System.out.println(sum);}
}
总结与资源推荐
总结:本届题目注重数学规律与基础算法的结合,如异或特性、素数筛、动态规划等。备赛时需强化数论知识,掌握经典算法模板,并注意大数运算的溢出问题。
官方资源:
- 题目下载:蓝桥杯官网
- 在线评测:C语言网
注意事项:实际编码时需优先优化时间复杂度,例如D题通过素数筛预处理可大幅提升效率。