试题 D: 合并检测
本题总分:10 分
【问题描述】
最近存在A病,最近在 A 国蔓延,为了尽快控制病*,A 国准备给大量民众进病*检测。
然而,用于检测的试剂盒紧缺。
为了解决这一困难,科学家想了一个办法:合并检测。即将从多个人(k个)采集的标本放到同一个试剂盒中进行检测。如果结果为阴性,则说明这 k个人都是阴性,用一个试剂盒完成了 k 个人的检测。如果结果为阳性,则说明至少有一个人为阳性,需要将这 k 个人的样本全部重新独立检测(从理论上看,如果检测前 k 1 个人都是阴性可以推断出第 k 个人是阳性,但是在实际操作中不会利用此推断,而是将 k 个人独立检测),加上最开始的合并检测,一共使用了 k + 1 个试剂盒完成了 k 个人的检测。
A 国估计被测的民众的感染率大概是 1%,呈均匀分布。请问 k 取多少能最节省试剂盒?
【答案提交】
这是一道结果填空题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
【解题思路】
这道题的问题:
- A国的人数,这个就是定义一个变量allPerson,去假定一个人数,eg:100,10000,782等等
- 多个标本k放到同一个试剂盒中的k如何定义。k的最小值就是1,就是一个人一个试剂盒的情况,这也是最好的情况了,k的范围在(1 ~ allPerson),其实k也不可能为总人数,就是所有人用一个试剂盒的情况,这个肯定不现实。但由于检测的试剂盒紧缺,所以k不可能太小,也不可能太大,这个我们就可以定一个合理的范围(1 ~ 100)即可
- 测出感染后需要使用的试剂盒数量,因为它感染的人那个试剂盒内的k个标本要通过k个试剂盒单个检验。已知的是感染率是1%,而且感染的人是平均分布的,所以不用去考虑几个感染在一块儿的情况。所以测出感染后需要使用的试剂盒数量 = (1% × 人数)× k ;其中(1% × 人数) 得到的感染人数,并且感染人数肯定是一个整数,这里就需要通过进行向上取整或向下取整来得到感染人数。
- 人数能否被k整除。因为能整除的话,(人数/k)就相当于几个试剂盒。如果不能整除的话,那么它的试剂盒需要再+1用来测试最后剩下来的人的感染情况(剩下的人数肯定是小于8的),我们不需要去考虑剩下的人存在感染情况的可能,因为前面的(0.01人数k)得到的已经是最大的测出感染后需要使用的试剂盒。
解题思路如下:
- 假定A国人数,定义试剂盒个数,试剂盒最小个数,以及最后结果
- k标本再定义范围内的循环,看几个标本使用一个试剂盒最合适
- 判断(人数/k)能否被整除(即人数%k是否=0)
- 能整除的试剂盒个数 = (人数/ k) + (int) Math.floor(0.01 * 人数) * k;
- 不能整除的试剂盒个数 = (人数/ k) + (int) Math.floor(0.01 * 人数) * k + 1;
- 判断出最小最合适的情况即可
【代码如下】
/**
* 估计被测的民众的感染率大概是 1%,呈均匀分布。请问 k 取多少能最节省试剂盒?
*
* @author hf
*
*/
public class Blogs3 {
public static void main(String[] args) {
int allPerson = 999; // 随机确定的人数
int num = 0; // 试剂盒的个数
int minx = 9999999; // 试剂盒最少的个数
int answer = 0; // 答案
for (int k = 1; k <= allPerson; k++) {
if (allPerson % k == 0) {
num = (allPerson / k) + (int) Math.floor(0.01 * allPerson) * k;
} else {
num = (allPerson / k) + (int) Math.floor(0.01 * allPerson) * k + 1;
}
// 判断出最小试剂盒的情况就ok了
if (num < minx) {
minx = num;
// System.out.println(num);
answer = k;
}
}
System.out.println(answer);
}
}
【填空结果】
试题 E: REPEAT 程序
本题总分:15 分
【问题描述】
附件 prog.txt 中是一个用某种语言写的程序。
其中 REPEAT k 表示一个次数为 k 的循环。循环控制的范围由缩进表达,
从次行开始连续的缩进比该行多的(前面的空白更长的)为循环包含的内容。
例如如下片段:
该片段中从A = A + 4 所在的行到 A = A + 8 所在的行都在第一行的循环两次中。
REPEAT 6: 所在的行到 A = A + 7 所在的行都在 REPEAT 5: 循环中。
A = A + 5 实际总共的循环次数是 2 × 5 × 6 = 60 次。
请问该程序执行完毕之后,A 的值是多少?
【答案提交】
这是一道结果填空题,你只需要算出结果后提交即可。本题的结果为一个
整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
【解题思路】
这道题按照给的循环嵌套格式将代码写出来,最后直接打印就可以了。
因为这到题上面它提示到 A = A + 5 实际总共的循环次数是 2 × 5 × 6 = 60 次。这个就打消了让手算的可能。
【代码如下】
/**
* 试题 E: REPEAT 程序
* @author hf
*
*/
public class Blogs4 {
public static void main(String[] args) {
int A = 0; //a的值
for (int i = 0; i < 2; i++) {
A += 4;
for (int j = 0; j < 5; j++) {
for (int k = 0; k < 6; k++) {
A += 5;
}
A += 7;
}
A += 8;
}
A += 9;
System.out.println(A);
}
}
【填空结果】
试题 F: 分类计数
本题总分:15 分
【问题描述】
输入一个字符串,请输出这个字符串包含多少个大写字母,多少个小写字母,多少个数字。
【输入格式】
输入一行包含一个字符串。
【输出格式】
输出三行,每行一个整数,分别表示大写字母、小写字母和数字的个数。
【样例输入】
1+a=Aab
【样例输出】
1
3
1
【解题思路】
这道题不难,思路如下:
- 先将输入的字符串通过.toCharArray()变成字符数组
- 定义一个数组来进行统计大写字母、小写字母和数字的个数
- 循环数组并通过ASCII码或者直接的范围(0 ~ 9;a ~ z;A ~ Z)进行判断
- 判断出来就在对应的下标上+1
- 最后遍历打印
【代码如下】
import java.util.Scanner;
/**
* 输入一个字符串,请输出这个字符串包含多少个大写字母,多少个小写字母,多少个数字。
* @author hf
*
*/
public class Blogs5 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String str = sc.next();
char [] ch = str.toCharArray();
int [] num = new int [3];
for (int i = 0; i < ch.length; i++) {
if (ch[i] >= '0' && ch[i] <= '9') {
num[2]++;
}else if (ch[i] >= 'a' && ch[i] <= 'z') {
num[1]++;
}else if (ch[i] >= 'A' && ch[i] <= 'Z') {
num[0]++;
}
}
for (int i : num) {
System.out.println(i);
}
sc.close();
}
}
【样例结果】