求某一范围内纯质数--优化算法(java)

求某一范围内纯质数–优化算法(java)

话不多说上题目(2021年蓝桥杯国赛javaB组)

在这里插入图片描述

一般来说正常思路都是先判断是否是质数,然后判断是否是纯质数,因为纯质数的每个位置上只有2,3,4,7这四种可能,所以耗时最长的是判断是否是质数,一般算法都是从2开始判断到n(n*n<=要判断的数)能否整除要判断的数,如下所示(该代码为网上随意找的,思路差不多。):

public class Test1 {
	static int number=20210605;//测试的上限
	static int map[]=new int[number];
	static ArrayList<String> ans=new ArrayList();
	static int anscount=0;

	public static void main(String[] args) {
		int count=0;
		//此for循环找出范围内所有的质数
		for (int i = 2; i <= number; i++) {
			boolean add=true;
			for (int j = 2; j*j <= i; j++) {
				if(i%j==0) {
					add=false;
					continue;
				}
			}
			if(add==true) {
				map[count]=i;
				count++;
			}
		}
//		System.out.println("wanbi");
		//此for循环对每个质数进行判断
		for (int i = 0; i < count; i++) {
			String single = String.valueOf(map[i]);
//			System.out.print(single+"   ");
			boolean shi=true;
			//将这个质数转化为字符串后将其的每一个字符转化为数字
			flag: for (int j = 0; j < single.length(); j++) {
				Integer wei = Integer.valueOf(single.charAt(j)-48);
				//排除1和0
				if(wei==1 || wei==0) {
					shi=false;
					break;
				}
				//判断这个位数是不是质数
				for (int k = 2; k*k <=wei; k++) {
					if(wei%k==0) {
						shi=false;
						break flag;
					}
				}
//				System.out.print(wei+"  ");
			}
			//如果这个质数是纯质数的话,总和+1
			if(shi==true) {
				System.out.println(single);
				ans.add(single);
				anscount++;
			}
//			System.out.println();

		}
		//调试时的输出语句
//		for (int i = 0; i < count; i++) {
//			System.out.print(map[i]+" ");
//		}
//		System.out.println();
//		for (int i = 0; i < ans.size(); i++) {
//			System.out.print(ans.get(i)+" ");
//		}
		System.out.println();
		System.out.println(anscount);
	}
}

经过运行发现就算只是查到20210605这一数字,也要运行大概十几分钟。当要查的数字增大时,该时间会更大。

下面我们对算法进行优化,首先,所有的偶数(2除外)都不会是质数,所以我们可以将外层循环从3开始,步进为2,这样可以减少一半的循环。但是效率还不是很高。

所以我们只能对判断质数的算法进行下手。

先解释一下为什么只判断到n(n*n<=要判断的数(i代替)):

在这里插入图片描述

然后对算法进行转化:

在这里插入图片描述

基于上述结论,将求质数的算法进行调整:

int numb = 20210605;
//存放已经找到的质数
ArrayList<Integer> list = new ArrayList<>();
//因为2也是纯质数,并且循环是从3开始,所以先将2放入集合
list.add(2);
for (int i = 3; i <= numb; i=i+2) {
    boolean flag = true;
    for (int j = 0 ;list.get(j)*list.get(j)<=i;j++) {
        if (i%list.get(j)==0){
            flag = false;
            break;
        }
    }
    if (flag){
        list.add(i);
        System.out.println(i);
    }
}

在求质数的基础上添加判断纯质数的代码:

public class Test2 {
    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        System.out.println(start);
        int numb = 20210605;
        int count = 0;
        ArrayList<Integer> list = new ArrayList<>();
        list.add(2);
        //因为2也是纯质数,并且循环是从3开始,所以先加1
        count++;
        System.out.println(2);

        for (int i = 3; i <= numb; i=i+2) {
            boolean flag = true;
            for (int j = 0 ;list.get(j)*list.get(j)<=i;j++) {
                if (i%list.get(j)==0){
                    flag = false;
                    break;
                }
            }
            if (flag){
                list.add(i);
                boolean matches = Pattern.matches("[2357]+", i + "");
                if (matches){
                    System.out.println(i);
                    count++;
                }
            }
        }
        System.out.println("数量:"+count);
        System.out.println("时间:"+(System.currentTimeMillis()-start));
    }
}


         }
        }
        System.out.println("数量:"+count);
        System.out.println("时间:"+(System.currentTimeMillis()-start));
    }
}

经验证原本的算法时间大概需要十几分钟,优化后的代码约为5秒钟。效率有很大的提升,但是算法是我自己进行的转化,数学上的严谨性有待验证,如有不妥之处,还请各位数学大神指点,或者论证一下算法是否可行。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值