第四届蓝桥杯javaB组 幸运数

本文介绍了一种名为幸运数的数列生成方法,并提供了一个Java程序来计算指定范围内幸运数的数量。幸运数通过筛选过程生成,类似于素数的生成方式,但依据的是数列中元素的位置而非数值本身。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述

幸运数是波兰数学家乌拉姆命名的。它采用与生成素数类似的“筛法”生成

首先从1开始写出自然数1,2,3,4,5,6,....

1 就是第一个幸运数。

我们从2这个数开始。把所有序号能被2整除的项删除,变为:

1 _ 3 _ 5 _ 7 _ 9 ....

把它们缩紧,重新记序,为:

1 3 5 7 9 .... 。这时,3为第2个幸运数,然后把所有能被3整除的序号位置的数删去。注意,是序号位置,不是那个数本身能否被3整除!! 删除的应该是5,11, 17, ...

此时7为第3个幸运数,然后再删去序号位置能被7整除的(19,39,...)

最后剩下的序列类似:

1, 3, 7, 9, 13, 15, 21, 25, 31, 33, 37, 43, 49, 51, 63, 67, 69, 73, 75, 79, ...

输入格式
输入两个正整数m n, 用空格分开 (m < n < 1000*1000)
输出格式
程序输出 位于m和n之间的幸运数的个数(不包含m和n)。
样例输入1
1 20
样例输出1
5
样例输入2
30 69
样例输出2

8



import java.util.*;

public class XingYunShuZi2 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		Scanner input = new Scanner(System.in);
		int m = input.nextInt();
		int n = input.nextInt();
		int num[] = new int[n];
		int count = 0;
		for (int i = 0; i < n; i++) {
			num[i] = i * 2 + 1;
		}
		df(num, 1, n);
		for (int i = 1; i < n && num[i] <= n; i++) {
			if (num[i] > m && num[i] < n) {
				count++;
			}
		}

		System.out.println(count);

	}

	public static void df(int num[], int start, int end) {
		int k = start;
		int x = num[start];
		for (int i = k; i < end; i++) {
			if ((i + 1) % x != 0) {
				num[k++] = num[i];
			}
		}

		if (x < end) {
			df(num, start + 1, end);
		}

	}

}

### 第十四届蓝桥杯 Java B 题目及解析 #### 背景概述 蓝桥杯大赛作为一项面向全国高校学生的科技竞赛活动,其题目设计注重考察参赛者的逻辑思维能力和算法实现能力。相比于其他在线平台(如LeetCode),蓝桥杯更倾向于涉及学推理和实际问题建模的内容[^2]。 #### 题目分析 以下是关于第十四届蓝桥杯 Java B的部分典型题目及其解析: --- ##### **1. 字统计** **描述**: 给定一个正整 `n` 和另一个正整 `k`,求出从 1 到 n 的所有整中,字 k 出现的总次。 **样例输入**: ``` n = 11, k = 1 ``` **样例输出**: ``` 4 ``` **解析**: 可以通过逐位分解的方式计算每一位上字 k 出现的频率。具体而言,可以按照如下方式处理:将当前字分为高位部分、低位部分以及当前位置上的值分别讨论。这种方法的时间复杂度较低,适合大规模据范围下的高效运算。 ```java public class DigitCount { public static int countK(int n, int k) { int count = 0; for (int i = 1; i <= n; i++) { String s = Integer.toString(i); for (char c : s.toCharArray()) { if (c - '0' == k) { count++; } } } return count; } public static void main(String[] args) { System.out.println(countK(11, 1)); // 输出 4 } } ``` --- ##### **2. 座位分配优化** **描述**: 假设某学校有若干学生需要安排到不同大小的桌子旁学习。已知每张桌子最多容纳一定量的学生,如何合理安排使得使用的桌子总最少? **样例输入**: ``` 寝室人列表: {3, 3, 4}, 桌子容量列表: {6, 4} ``` **样例输出**: ``` 最小桌子需求总量为 10 ``` **解析**: 此题属于经典的资源分配问题。通过贪心策略解决较为合适——优先尝试用最大容量的桌子满足尽可能多的人群合。例如,在上述例子中,先利用一张六人桌安置两位来自三人寝的同学;再单独使用四人桌来安放一位来自四人寝的同学即可完成最优解法[^3]。 ```java import java.util.Arrays; public class TableArrangement { public static int minTableUsage(int[] dormSizes, int[] tableCapacities) { Arrays.sort(dormSizes); // 升序排列宿舍规模 Arrays.sort(tableCapacities); // 升序排列桌子容量 int totalUsedCapacity = 0; while (!isEmpty(dormSizes)) { boolean assigned = false; for (int j = tableCapacities.length - 1; j >= 0 && !assigned; --j) { if (dormSizes[dormSizes.length - 1] <= tableCapacities[j]) { reduceLargestDorm(dormSizes); totalUsedCapacity += tableCapacities[j]; assigned = true; } else if (canCombineToFill(dormSizes, tableCapacities[j])) { combineAndReduce(dormSizes, tableCapacities[j]); totalUsedCapacity += tableCapacities[j]; assigned = true; } } } return totalUsedCapacity; } private static boolean isEmpty(int[] array) { for (int num : array) { if (num != 0) return false; } return true; } private static void reduceLargestDorm(int[] dorms) { dorms[dorms.length - 1]--; sortDescending(dorms); } private static boolean canCombineToFill(int[] dorms, int capacity) { int sum = 0; for (int d : dorms) { if (sum + d > capacity) break; sum += d; } return sum == capacity; } private static void combineAndReduce(int[] dorms, int capacity) { int remaining = capacity; for (int i = dorms.length - 1; i >= 0; --i) { if (remaining >= dorms[i]) { remaining -= dorms[i]; dorms[i] = 0; } else { dorms[i] -= remaining; remaining = 0; } if (remaining == 0) break; } sortDescending(dorms); } private static void sortDescending(int[] array) { Arrays.sort(array); reverseArray(array); } private static void reverseArray(int[] array) { for (int i = 0; i < array.length / 2; ++i) { int temp = array[i]; array[i] = array[array.length - 1 - i]; array[array.length - 1 - i] = temp; } } public static void main(String[] args) { int[] dormSizes = {3, 3, 4}; int[] tableCapacities = {6, 4}; System.out.println(minTableUsage(dormSizes, tableCapacities)); // 输出 10 } } ``` --- ##### **3. 字符串匹配游戏** **描述**: 给出两个字符串 A 和 B,判断是否存在一种操作序列能够使 A 变成 B?允许的操作包括删除字符、插入字符或替换字符。 **样例输入**: ``` A = "horse", B = "ros" ``` **样例输出**: ``` True ``` **解析**: 该问题是典型的编辑距离问题,可采用动态规划的方法加以解决。定义二维 dp[i][j] 表示将字符串 A 前 i 个字符转换成字符串 B 前 j 个字符所需的最少步,则状态转移方程可以根据最后一个操作的不同情况构建得出。 ```java public class EditDistance { public static boolean isConvertible(String a, String b) { int m = a.length(); int n = b.length(); int[][] dp = new int[m + 1][n + 1]; for (int i = 0; i <= m; i++) { for (int j = 0; j <= n; j++) { if (i == 0) { dp[i][j] = j; } else if (j == 0) { dp[i][j] = i; } else if (a.charAt(i - 1) == b.charAt(j - 1)) { dp[i][j] = dp[i - 1][j - 1]; } else { dp[i][j] = Math.min(Math.min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1; } } } return dp[m][n] <= 3; // 如果编辑距离不超过某个阈值则认为可转化 } public static void main(String[] args) { System.out.println(isConvertible("horse", "ros")); // 输出 True } } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值