题目描述
小 A 有一个质数口袋,里面可以装各个质数。他从 2 2 2 开始,依次判断各个自然数是不是质数,如果是质数就会把这个数字装入口袋。
口袋的负载量就是口袋里的所有数字之和。
但是口袋的承重量有限,装的质数的和不能超过 L L L。给出 L L L,请问口袋里能装下几个质数?将这些质数从小往大输出,然后输出最多能装下的质数的个数,数字之间用换行隔开。
输入格式
一行一个正整数 L L L。
输出格式
将这些质数从小往大输出,然后输出最多能装下的质数个数,所有数字之间有一空行。
样例 #1
样例输入 #1
100
样例输出 #1
2
3
5
7
11
13
17
19
23
9
样例 #2
样例输入 #2
5
样例输出 #2
2
3
2
样例 #3
样例输入 #3
11
样例输出 #3
2
3
5
3
提示
数据保证, 1 ≤ L ≤ 10 5 1 \le L \le {10}^5 1≤L≤105。
代码:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int k = sc.nextInt();
int num[] = new int[10000];
num[0] = 2;
int sum = 2;
int count = 1;
int i = 2;
while (sum <= k) {
if (zhishu(i)) {
num[i] = i;
sum += i;
i++;
count++;
if (sum > k) {
count--;
i--;
num[i] = 0;
break;
}
} else i++;
}
if (k == 1) {
System.out.println(0);
} else {
for (int j = 0; j <= i; j++) {
if (num[j] != 0) {
System.out.println(num[j]);
}
}
System.out.println(count);
}
}
public static boolean zhishu(int num){
boolean bl = false;
for(int i = 2;i<=num-1;i++){
if(num%i == 0){
bl = false;
break;
}
if(i==num-1){
bl = true;
}
}
return bl;
}
}
这个代码虽然正确,但是num[]
与sum
的临界处处理的并不好。其中,在质数判断中,借助num
对i
取余的结果为b1
赋值,得到num
是否为质数的真值情况。为了避免讨论num=2
的情况,我们对num[]
进行了部分初始化。在sum
临界处,为了避免sum+=i
之后sum>=k
的情况,在sum
运算后我们对sum
进行了检验。最后对k=1
的情况分开讨论。
可以看出,这个代码还是很粗糙的
借助人工智能,有以下代码:
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class PrimePocket {
// 判断一个数是否为质数
private static boolean isPrime(int num) {
if (num <= 1) return false;
for (int i = 2; i * i <= num; i++) {
if (num % i == 0) return false;
}
return true;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int L = sc.nextInt();
sc.close();
List<Integer> primes = new ArrayList<>();
int sum = 0;
int maxCount = 0;
for (int i = 2; sum + i <= L; i++) {
if (isPrime(i)) {
primes.add(i);
sum += i;
maxCount++;
}
}
// 输出质数
for (int prime : primes) {
System.out.println(prime);
}
// 输出最多能装下的质数个数
System.out.println(maxCount);
}
}
1 优化指数判断
在所给的代码段中,循环的条件是 i * i <= num
,这是一个优化技巧,称为 “平方根优化” 或 “试除法优化”。
考虑判断一个数 num
是否为质数。一般来说,我们需要检查 num
能否被 2 到 num - 1
之间的整数整除。但是实际上,我们只需要检查 num
能否被 2 到 sqrt(num)
之间的整数整除,即 i * i <= num
。
这是因为如果 num
有一个大于 sqrt(num)
的因数,那么它必然也有一个小于 sqrt(num)
的因数。因此,我们只需要检查到 sqrt(num)
就足够了。
例如,如果 num
是一个合数,即有一个大于 1 和小于 num
的因数 d
,那么必然有 d = a * b
,其中 a
和 b
都是正整数。如果 a
大于等于 sqrt(num)
,那么 b
必然小于等于 sqrt(num)
。同理,如果 b
大于等于 sqrt(num)
,那么 a
必然小于等于 sqrt(num)
。因此,只需要检查到 sqrt(num)
就可以判断 num
是否为质数。
所以,使用 i * i <= num
作为循环条件,可以减少循环的次数,提高程序的效率。
2 优化sum的临界处处理
在循环的判断条件了,将i的判断改为sum+i
的判断。
3 优化键值对应
利用ArrayList
集合将符合条件的num
收入集合之中,并利用foreach
语句对目标集合打印。
--------------------蓝桥杯备赛系列正在不断更新中,欢迎各位大佬指导----------------------------------------------