1. 问题描述:
幸运数是波兰数学家乌拉姆命名的。它采用与生成素数类似的“筛法”生成。
首先从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 20
程序输出:
5
例如:
用户输入:
30 69
程序输出:
8
资源约定:
峰值内存消耗(含虚拟机) < 64M
CPU消耗 < 2000ms
2. 思路分析:
① 主要是根据题目描述转化为代码的逻辑表示,首先我们可以先声明一个长度为n的数组并且对其初始化为奇数,相当于把其中的偶数都删除掉了,声明一个变量表示的是幸运数的下标,在循环中我们判断当前的下标是否能够被幸运数的下标
所对应的数字整除,如果能够整除说明当前这个下标对应的数字应该删除,但是对于当前这种情况我们什么什么也不干,如果是不能够整除那么我们当前的数字不能够删除,所以我们采取的方法是将不被删掉的数字往前进行移动,之前需要被删除的数字都会被覆盖掉所以需要一个变量p来记录当前这个下标对应的数字应该移动到什么地方,一轮循环结束所有不被删除的数字都是在0-p对应的数组位置上,p之后的也是不被删除的数字,其中有的位置上可能有重复的数字
这个时候应该将幸运数的下标加一来看一下当前数组对应的元素是否大于等于了需要求解的右区间,假如判断成立那么应该退出最外面的while循环,不成立的话继续上面的筛选
② 我们知道后面数字假如不被整除那么会覆盖之前的数字,而且越往后面的时候不被整除的数字越少,所以往大部分进行往前移动
3. 代码如下:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int m = sc.nextInt();
int n = sc.nextInt();
int arr[] = new int[n];
for(int i = 0; i < n; i++){
arr[i] = 2 * i + 1;
}
int l = 1;
while(true){
int p = l + 1;
for(int i = l + 1; i < n; i++){
if((i + 1) % arr[l] == 0){
}else{
arr[p++] = arr[i];
}
if(arr[p] > n) break;
}
l++;
if(arr[l] > n)break;
}
int count = 0;
for(int i = 0; i < n; i++){
if(arr[i] >= n) break;
if(arr[i] >= m) count++;
}
System.out.println(count);
sc.close();
}
}