蓝桥杯:幸运数

目录

题目描述

输入描述

输出描述

输入输出样例

题目分析:列表枚举

AC代码(Java):


题目描述

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

首先从 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 < 10^6)。

输出描述

输出位于 m 和 n 之间的幸运数的个数(不包含 m 和 n )。

输入输出样例

输入 

1 20

 输出

5

题目分析:列表枚举

        1.照例先分析题目,幸运数是从1开始的,一直往后,然后1是第一个自然数,就不管他,让第一个幸运数从2开始,就是删除所有下标能被2整除的数。

        2.这里看到需要频繁删除,首先排除数组来做(用数组做也不是不行),可以用列表。

        3.然后看数据范围,它给的提示是 m和n,但是幸运数是从1开始的,也就是说我们需要填充1到n的数据进列表里面。然后删除完毕之后再判断m-n范围内的数据有多少即可。

        4.因为列表的特性(删除了i,那么i的位置就会被i+1补上),所以我们删除要从末尾开始,依次往前删除,也就是 从len 到 1;

        5.循环读取幸运数删除即可,每次拿到幸运数,通过一个方法,逆向删除所有能被该幸运数整除的下标即可。

AC代码(Java):

import java.util.*;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        //题目描述是很有问题,简单来说,就是这些幸运数是从1开始填充到N的,然后第一个幸运数为2,就是删除偶数位置的值
        //然后第二个幸运数就是列表中的第三个数(列表我们额外填充一个0,这样1的下标就是1,模拟出了题目的情况)
        int m = scan.nextInt();
        int n = scan.nextInt();
        scan.close();
        List<Integer> list = new ArrayList<>();
        //因为下标都是从0开始,我们为了模拟题目要求,多填充一个0
        list.add(0);
        //填充数据
        for(int i = 1;i<=n;i++){
            list.add(i);
        }
        //幸运数从1开始,直到列表的长度(超出列表的长度代表幸运数已经处理完了,接下来只需要统计m-n范围的数据即可)
        int luck = 1;
        while(luck<list.size()){
            //处理一开始的特殊情况(第一个幸运数是1,那么就顺延到下一个,也就是2)
            if(luck == 1){
                delete(list,2);
            }else{
                delete(list,list.get(luck));
            }
            luck++;
        }
        //删除完之后遍历一下看看list剩余
        int number = 0;
        for(int i : list){
            if(i>m && i<n){
                number++;
            }
        }
        System.out.println(number);
    }
    /*删除能被luck整除的下标*/
    public static void delete(List<Integer> list,int luck){
        //一般都是从末尾开始删除,不然会因为列表的特性(删了i位置的,i+1位置的会补上来)出错
        int len = list.size()-1;
        for(int i = len;i>0;i--){
            if(i%luck == 0){
                list.remove(i);
            }
        }
    }
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值