蓝桥杯第11届省赛7月份试题javaB组
1 解密
-
题目:
小明设计了一种文章加密的方法:对于每个字母 C,将它变成某个另外的字符 Tc 。下表给出了字符变换的规则: 例如,将字符串 YeRi 加密可得字符串 EaFn。 小明有一个随机的字符串,加密后为EaFnjISplhFviDhwFbEjRjfIBBkRyY(由 30 个大小写英文字母组成,不包含换行符),请问原字符串是多少?
-
题解分析
- 定义两个数组,分别存储原字符和加密字符
- 把加密的字符在加密数组中找到然后在根据字符的下标索引找到原字符。
-
代码
public class Demo01 {
public static void main(String[] args) {
int index;
String s1 ="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";//原字符
String s2 ="yxmdacikntjhqlgoufszpwbrevYZMDACIKNTJHQLGOUFSZPWBREV";//加密字符
String str ="EaFnjISplhFviDhwFbEjRjfIBBkRyY";//随机加密字符
char arr[] = str.toCharArray();
StringBuffer sb = new StringBuffer();
for(int i =0 ;i<arr.length;i++){
index = s2.indexOf(arr[i]);
sb.append(s1.charAt(index));
}
System.out.println(sb.toString());
}
}
- 答案:YeRikGSunlRzgDlvRwYkXkrGWWhXaA
2 纪念日
- 题目
问题描述:
2020 年 7 月 1 日是中国共产党成立 99 周年纪念日。
中国共产党成立于 1921 年 7 月 23 日。
请问从 1921 年 7 月 23 日中午 12 时到 2020 年 7 月 1 日中午 12 时一共包含多少分钟?
-
题解分析
- 直接调用Data类得到毫秒数然后转化成分钟
-
代码
public class Demo02 {
public static void main(String[] args) throws Exception {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Date data1 = format.parse("1921-07-23");
Date data2 = format.parse("2020-07-01");
//获取相差的毫秒数
long data1Time = data1.getTime();
long data2Time = data2.getTime();
System.out.println((data2Time-data1Time)/(1000*60));
}
}
- 答案: 52038720
3 合并检测
- 题目
新冠疫情由新冠病毒引起,最近在 A 国蔓延,为了尽快控制疫情,
A 国准备给大量民众进病毒核酸检测。然而,用于检测的试剂盒紧缺。
为了解决这一困难,科学家想了一个办法:合并检测。
即将从多个人(k个)采集的标本放到同一个试剂盒中进行检测。
如果结果为阴性,则说明这 k个人都是阴性,用一个试剂盒完成了 k 个人的检测。
如果结果为阳性,则说明至少有一个人为阳性,需要将这 k 个人的样本全部重新独立检测
(从理论上看,如果检测前 k−1 个人都是阴性可以推断出第 k 个人是阳性,
但是在实际操作中不会利用此推断,而是将 k 个人独立检测),
加上最开始的合并检测,一共使用了 k + 1 个试剂盒完成了 k 个人的检测。
A 国估计被测的民众的感染率大概是 1%,呈均匀分布。请问 k 取多少能最节省试剂盒
-
分析:
-
这个题可以用数学的解法,设有n个人检查。然后一组分配k个人,共n/k组,假如有感染的情况,0.01nk(感染人的概率)。
则一共需要的试剂为y=n/k+0.01nk, 求导后令y=0即可的到K=10;
-
-
代码:暴力求解
public class Demo03 {
public static void main(String[] args) {
int min =0 ;
int sum=Integer.MAX_VALUE;
System.out.println(sum);
for(int i=1 ;i<100;i++){
if(100%i==0){
if(100/i+i<sum){
sum=100/i+i;
min=i;
}
}
else {
if(100/i+1+i<sum){
sum=100/i+1+i;
min=i;
}
}
}
System.out.println(min);
}
}
- 答案: 10
4 分配口罩
- 题目表述:
某市市长获得了若干批口罩,每一批口罩的数目如下
:(如果你把以下文字复制到文本文件中,请务必检查复制的内容是否与文档中的一致。
在试题目录下有一个文件 mask.txt,内容与下面的文本相同)
现在市长要把口罩分配给市内的 2 所医院。由于物流限制,每一批口罩只能全部分配给其中一家医院。
市长希望 2 所医院获得的口罩总数之差越小越好。请你计算这个差最小是多少?
- 分析
- 方法一: 可以用分配法,先求出所有口罩的数目然后在求平均值ave。用 dp[j]=Math.max(dp[j],dp[j-nums[i]]+nums[i])可以得到分配口罩的差数,因为两家的差数对ave是相同的所以最后在乘2.
- 方法二:利用dfs暴力遍历类似与0 1 二叉数。
- 代码:
public class Demo04 {
public static void main(String[] args) {
int sum = 0 , ave = 0;
int[] nums = {0, 9090400, 8499400, 5926800, 8547000, 4958200,
4422600, 5751200, 4175600, 6309600, 5865200, 6604400, 4635000,
10663400, 8087200, 4554000};
for (int i = 0; i < nums.length; i++) {
sum = sum + nums[i];
}
ave = sum / 2;
int[] dp = new int[ave+1];
for (int i = 1; i < nums.length; i++) {
for (int j = ave; j >= nums[i]; j--) {
dp[j]=Math.max(dp[j],dp[j-nums[i]]+nums[i]);
}
}
System.out.println(2 * (ave - dp[ave]));
}
/* public static long res=Long.MAX_VALUE;
public static long num[]={9090400, 8499400, 5926800, 8547000, 4958200,
4422600, 5751200, 4175600, 6309600, 5865200,
6604400, 4635000, 10663400, 8087200, 4554000
};
public static void main(String[] args){
dfs(0, 0, 0);
System.out.println(res);
}
public static void dfs(int k,long sum1,long sum2 ) {
if(k==15) {
res=res<Math.abs(sum1-sum2)?res:Math.abs(sum1-sum2);
return;
}
dfs(k+1, sum1+num[k], sum2);
dfs(k+1, sum1, sum2+num[k]);
}
*/
}
- 答案: 2400
5 斐波那契数列最大公约数
- 题目
问题描述:
- 分析
- 由于求这个数太大用int long 都会爆 超出后会按-1计算导致结果不对,所以我们用大数BigIntegr 计算,然后调用里面的gcd求最大公约数
- 代码:
public class Demo05 {
public static void main(String[] args) {
BigInteger [] arr = new BigInteger[2025];
arr[0]=BigInteger.ZERO;
arr[1]=arr[2]=BigInteger.ONE;
System.out.println(arr[0]);
for(int i =3;i<=2020;i++){
arr[i]=arr[i-1].add(arr[i-2]);
}
System.out.println(arr[520]);
System.out.println();
System.out.println();
System.out.println(arr[2020]);
BigInteger gcd = arr[2020].gcd(arr[520]);
System.out.println(gcd);
}
}
- 答案: 6765
6 分类求和
- 问题描述:
输入一个字符串,请输出这个字符串包含多少个大写字母,多少个小写字母,多少个数字。
输入格式:
输入一行包含一个字符串。
输出格式:
输出三行,每行一个整数,分别表示大写字母、小写字母和数字的个数。
样例输入
1+a=Aab
样例输出
1
3
1
对于所有评测用例,字符串由可见字符组成,长度不超过 100。
- 代码
public class Demo06 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String str = scanner.next();
char[] arr = str.toCharArray();
int countAZ = 0;
int countaz = 0;
int countNum = 0;
// 遍历字符数组
for (int i = 0; i < arr.length; i++) {
if (arr[i] >= 'A' && arr[i] <= 'Z'){
countAZ++;
}
if (arr[i] >= 'a' && arr[i] <= 'z'){
countaz++;
}
if (arr[i] >= '0' && arr[i] <= '9'){
countNum++;
}
}
System.out.println(countAZ);
System.out.println(countaz);
System.out.println(countNum);
}
}
- 答案 :
7 8次求和
- 题目
问题描述
给定正整数 n, 求 1^8 + 2^8 + ··· + n^8 mod 123456789 。其中 mod 表示取余。
输入格式
输入的第一行包含一个整数 n。
输出格式
输出一行,包含一个整数,表示答案
- 分析
- 这个数的八次方很大不能用Int 俺们要用BigIntegeer ,里面有pow求次方,mod求余的方法
- 代码:
public class Demo07 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
BigInteger ans = BigInteger.ZERO;
BigInteger modd = BigInteger.valueOf(123456789);
for(int i =1;i<=n;i++){
BigInteger res = BigInteger.valueOf(i);
ans = ans.add(res.pow(8));
/* ans =ans.add(res.multiply(res).multiply(res).multiply(res).multiply(res).multiply(res).multiply(res).
multiply(res));*/
}
System.out.println(ans.mod(modd));
}
}
8 字符串编码
- 题目
问题描述:
小明发明了一种给由全大写字母组成的字符串编码的方法。对于每一个大写字母,
小明将它转换成它在 26 个英文字母中序号,即 A → 1, B → 2, ... Z →26。
这样一个字符串就能被转化成一个数字序列:比如 ABCXYZ → 123242526。
现在给定一个转换后的数字序列,小明想还原出原本的字符串。
当然这样的还原有可能存在多个符合条件的字符串。小明希望找出其中字典序最大的字符串。
-
分析
- 首先我们会定义一个数组来存26个大写字母,当我们输入字符串类型的数字要考虑它识别的数字是不是最大的字母,是按照两位数识别还是个位数识别,我们发现字母最多只有26个。即两位数只要<=26就会有字母输出。
- 我们也要考虑特殊情况如果后面数字是0,那么这个0的归属是前面还是后面呢。如1201(这个后面才知道的没有写判断)
-
代码:
public class Demo08 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
char arr[] = {'0',
'A','B','C','D','E','F','G','H','I','J','K',
'L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'
};
String str = sc.next();
String res = "";
for(int i=0;i<str.length();i++){
if(i+1<str.length()){
int temp = (str.charAt(i)-'0')*10+(str.charAt(i+1)-'0');
if(temp<=26){
res=res + new String().valueOf(arr[temp]);
i++;
} else {
res=res + new String().valueOf(arr[str.charAt(i)-'0']);
}
}else {
res = res +new String().valueOf(arr[str.charAt(i)-'0']);
}
}
System.out.println(res);
}
}
9 BST插入节点问题
- 题目
时间限制: 1.0s 内存限制: 512.0MB 本题总分:25 分
【问题描述】
给定一棵包含 N 个节点的二叉树,节点编号是 1 ∼ N。其中 i 号节点具有权值 Wi,并且这些节点的权值恰好形成了一棵排序二叉树 (BST)。
现在给定一个节点编号 K,小明想知道,在这 N 个权值以外,有多少个整数 X (即 X 不等于任何 Wi ) 满足:给编号为 K 的节点增加一个权值为 X 的子节点,仍可以得到一棵 BST。
例如在下图中,括号外的数字表示编号、括号内的数字表示权值。即编号
1 ∼ 4 的节点权值依次是 0、10、20、30。
如果 K = 1,那么答案为 0。因为 1 号节点已经有左右子节点,不能再增加子节点了。
如果 K = 2,那么答案为无穷多。因为任何一个负数都可以作为 2 的左子节点。
如果 K = 3,那么答案为 9。因为 X = 11, 12, · · · , 19 都可以作为 3 的左子节点。
【输入格式】
第一行包含 2 个整数 N 和 K。
以下 N 行每行包含 2 个整数,其中第 i 行是编号为 i 的节点的父节点编号
Pi 和权值 Wi 。注意 Pi = 0 表示 i 是根节点。输入保证是一棵 BST。
【输出格式】
一个整数代表答案。如果答案是无穷多,输出 −1。
【样例输入】
4 3
0 10
1 0
1 20
3 30
【样例输出】
9
-
题解
- 从题目中我们知道k=2时答案有无穷多个,所以我们不把它看作根节点
- 即我们只需要考虑它作为左节点即可,当他为左节点时她会比自己的父节点要小,要比父节点的父节点要大
-
代码:
public class Demo09 {
static int MAX = Integer.MAX_VALUE;
static int MIN = Integer.MIN_VALUE;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int K = sc.nextInt();
INode [] node = new INode[N];
for(int i =0 ;i< N;i++){
int parentID = sc.nextInt();
int weight = sc.nextInt();
//第一个节点比较特殊,他的父节点是不存在的,并且他的左右节点都能填到无穷
if(i==0){
node[0]=new INode(1,parentID,weight,MIN,MAX);
}else{//其他节点的操作
int min = 0;
int max = 0;
INode parent = node[parentID-1];
//新的节点会代替父节点
//更新新节点的Min和max
if(weight>parent.weight){
//该节点保存的最小值应该比父亲节点的权值大1
min = parent.weight+1;
//最小值继承父亲节点
max = parent.maxValue;
//父节点保存的最大值变为权值
parent.maxValue= parent.weight;
}else{//添加左值节点
max = parent.weight-1;
min = parent.minValue;
parent.minValue = parent.weight;
}
node[i] = new INode(i+1,parentID,weight,min,max);
}
}
//如果有一个值为MIN或MAX就说明该节点可以添加无穷多的数
if(node[K-1].minValue==MIN||node[K-1].maxValue==MAX){
System.out.println(-1);
}else{
System.out.println(node[K-1].maxValue-node[K-1].minValue);
}
}
}
class INode{
int id;
int parentID;
int weight;
int minValue;
int maxValue;
public INode(int id,int parentID,int weight,int minValue,int maxValue){
this.id = id;
this.parentID = parentID;
this.weight = weight;
this.minValue= minValue;
this.maxValue= maxValue;
}
}
10 网络分析
-
这个我不会做 太难了!!!
-
分析:
- 这是一个无序图的遍历 当为1 的时候两个点相连接,当为2的时候给该点赋值(如果该点与其他点相互连接在一起后,也应该加上该点的赋值点)