以下均为个人想法和解题思路,如有错误或不足,欢迎指正。
试题 A: 门牌制作
本题总分:5 分
小蓝要为一条街的住户制作门牌号。
这条街一共有 2020 位住户,门牌号从 1 到 2020 编号。
小蓝制作门牌的方法是先制作 0 到 9 这几个数字字符,最后根据需要将字
符粘贴到门牌上,例如门牌 1017 需要依次粘贴字符 1、 0、 1、 7,即需要 1 个
字符 0, 2 个字符 1, 1 个字符 7。
请问要制作所有的 1 到 2020 号门牌,总共需要多少个字符 2?
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
个人答案:624
个人代码:
public class _门牌制作 {
public static void main(String[] args) {
int res = 0;
for(int i=1; i<=2020; ++i) {
int t = i;
while(t>0) {
if(t%10 == 2) {
++ res;
}
t /= 10;
}
}
System.out.println(res); //624
}
}
解题思路:第一题属于签到题,直接暴力就行了
试题 B: 寻找 2020
本题总分:5 分
小蓝有一个数字矩阵,里面只包含数字 0 和 2。小蓝很喜欢 2020,他想找
到这个数字矩阵中有多少个 2020 。
小蓝只关注三种构成 2020 的方式:
• 同一行里面连续四个字符从左到右构成 2020。
• 同一列里面连续四个字符从上到下构成 2020。
• 在一条从左上到右下的斜线上连续四个字符,从左上到右下构成 2020。
例如,对于下面的矩阵:
220000
000000
002202
000000
000022
002020
一共有 5 个 2020。其中 1 个是在同一行里的, 1 个是在同一列里的, 3 个
是斜线上的。
小蓝的矩阵比上面的矩阵要大,由于太大了,他只好将这个矩阵放在了一
个文件里面,在试题目录下有一个文件 2020.txt,里面给出了小蓝的矩阵。
请帮助小蓝确定在他的矩阵中有多少个 2020。
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
个人答案:16520
个人代码:
/**
* 使用文档编辑器打开考试给的txt文件,把光标定位至最后一个字符前面,可知共300行300列
*/
import java.util.Scanner;
public class _11_SS_B_寻找2020 {
static char[][] r = new char[300][300];
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
for(int i=0; i<300; ++i) {
r[i] = sc.nextLine().toCharArray();
}
int res = 0;
for(int i=0; i<300; ++i) {
for(int j=0; j+3<300; ++j) {
if(r[i][j]=='2' && r[i][j+1]=='0' && r[i][j+2]=='2' && r[i][j+3]=='0')
++ res;
}
}
for(int i=0; i+3<300; ++i) {
for(int j=0; j<300; ++j) {
if(r[i][j]=='2' && r[i+1][j]=='0' && r[i+2][j]=='2' && r[i+3][j]=='0')
++ res;
}
}
for(int i=0; i+3<300; ++i) {
for(int j=0; j+3<300; ++j) {
if(r[i][j]=='2' && r[i+1][j+1]=='0' && r[i+2][j+2]=='2' && r[i+3][j+3]=='0')
++ res;
}
}
System.out.println(res); //16520
}
}
解题思路:依旧暴力
试题 C: 蛇形填数
本题总分:10 分
如下图所示,小明用从 1 开始的正整数“蛇形”填充无限大的矩阵。
容易看出矩阵第二行第二列中的数是 5。请你计算矩阵中第 20 行第 20 列 的数是多少?
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
个人答案:761
个人代码:
public class _蛇形填数 {
public static void main(String[] args) {
int res = 1, t = 4;
for(int i=2; i<=20; ++i) {
res += t;
t += 4;
}
System.out.println(res); //761
}
}
解题思路:
试题 D: 七段码
本题总分:10 分
小蓝要用七段码数码管来表示一种特殊的文字。
上图给出了七段码数码管的一个图示,数码管中一共有 7 段可以发光的二极管,分别标记为 a, b, c, d, e, f, g。
小蓝要选择一部分二极管(至少要有一个)发光来表达字符。在设计字符的表达时,要求所有发光的二极管是连成一片的。
- 例如: b 发光,其他二极管不发光可以用来表达一种字符。
- 例如: c 发光,其他二极管不发光可以用来表达一种字符。这种 方案与上 一行的方案可以用来表示不同的字符,尽管看上去比较相似。
- 例如: a, b, c, d, e 发光, f, g 不发光可以用来表达一种字符。
- 例如: b, f 发光,其他二极管不发光则不能用来表达一种字符,因为发光 的二极管没有连成一片。
请问,小蓝可以用七段码数码管表达多少种不同的字符?
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
个人答案:80
个人代码:
import java.util.ArrayList;
import java.util.HashSet;
public class _七段码 {
static ArrayList<Integer>[] list;
static HashSet<Integer> set = new HashSet<Integer>();
public static void main(String[] args) {
init();
for(int i=0; i<7; ++i) {
vis[0] = i;
set.add(1<<i);
dfs(1, 1<<i);
}
System.out.println(set.size());
}
static int[] vis = new int[7];
public static void dfs(int n, int v) {
for(int i=0; i<n; ++i) {
for(int t : list[vis[i]]) {
int p = v|(1<<t);
if(!set.contains(p)) {
set.add(p);
vis[n] = t;
dfs(n+1, p);
}
}
}
}
/**
* 0
* 5 1
* 6
* 4 2
* 3
*/
public static void init() {
list = new ArrayList[7];
for(int i=0; i<7; ++i) {
list[i] = new ArrayList<Integer>();
}
list[0].add(1);
list[0].add(5);
list[1].add(0);
list[1].add(6);
list[1].add(2);
list[2].add(1);
list[2].add(3);
list[2].add(6);
list[3].add(2);
list[3].add(4);
list[4].add(3);
list[4].add(5);
list[4].add(6);
list[5].add(0);
list[5].add(4);
list[5].add(6);
list[6].add(1);
list[6].add(2);
list[6].add(4);
list[6].add(5);
}
}
解题思路:
试题 E: 排序
本题总分:15 分
小蓝最近学习了一些排序算法,其中冒泡排序让他印象深刻。在冒泡排序中,每次只能交换相邻的两个元素。
小蓝发现,如果对一个字符串中的字符排序,只允许交换相邻的两个字符,则在所有可能的排序方案中,冒泡排序的总交换次数是最少的。
例如,对于字符串 lan 排序,只需要 1 次交换。对于字符串 qiao 排序,总共需要 4 次交换。
小蓝找到了很多字符串试图排序,他恰巧碰到一个字符串,需要 100 次交换,可是他忘了吧这个字符串记下来,现在找不到了。
请帮助小蓝找一个只包含小写英文字母且没有字母重复出现的字符串,对该串的字符排序,正好需要 100 次交换。如果可能找到多个,请告诉小蓝最短的那个。如果最短的仍然有多个,请告诉小蓝字典序最小的那个。请注意字符串中不可以包含相同的字符。
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
个人答案:jonmlkihgfedcba
个人代码:
public class _排序{
public static void main(String[] args) {
for(int i=1; i<20; ++i) {
System.out.println(i+":"+((i-1)*i/2)); //由此可以发现15个字符的逆序通过冒泡交换成顺序所需要的交换次数最接近100,因此仅需要将onmlkjihgfedcba的第六位移动至第一位即可:jonmlkihgfedcba
}
}
}
解题思路:
试题 F: 成绩分析
时间限制: 1.0s 内存限制: 512.0MB 本题总分:15 分
小蓝给学生们组织了一场考试,卷面总分为 100 分,每个学生的得分都是 一个 0 到 100 的整数。
请计算这次考试的最高分、最低分和平均分。
输入的第一行包含一个整数 n,表示考试人数。 接下来 n 行,每行包含一个 0 至 100 的整数,表示一个学生的得分。
输出三行。
第一行包含一个整数,表示最高分。
第二行包含一个整数,表示最低分。
第三行包含一个实数,四舍五入保留正好两位小数,表示平均分。
7
80
92
56
74
88
99
10
99
10
71.29
对于 50% 的评测用例,1≤n≤100。
对于所有评测用例,1≤n≤10000。
个人代码:
import java.util.Scanner;
public class _11_SS_B_成绩分析 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int max = Integer.MIN_VALUE, min = Integer.MAX_VALUE;
double sum = 0;
for(int i=0; i<n; ++i) {
int t = sc.nextInt();
sum += t;
max = t>max?t:max;
min = t<min?t:min;
}
System.out.println(max);
System.out.println(min);
System.out.println(String.format("%.2f", sum/n));
}
}
解题思路:
试题 G: 单词分析
时间限制: 1.0s 内存限制: 512.0MB 本题总分:20 分
小蓝正在学习一门神奇的语言,这门语言中的单词都是由小写英文字母组 成,有些单词很长,远远超过正常英文单词的长度。小蓝学了很长时间也记不 住一些单词,他准备不再完全记忆这些单词,而是根据单词中哪个字母出现得 最多来分辨单词。
现在,请你帮助小蓝,给了一个单词后,帮助他找到出现最多的字母和这 个字母出现的次数。
输入一行包含一个单词,单词只由小写英文字母组成。
输出两行,第一行包含一个英文字母,表示单词中出现得最多的字母是哪 个。如果有多个字母出现的次数相等,输出字典序最小的那个。
第二行包含一个整数,表示出现得最多的那个字母在单词中出现的次数。
lanqiao
a
2
longlonglongistoolong
o
6
对于所有的评测用例,输入的单词长度不超过 1000。
个人代码:
import java.util.Scanner;
public class _11_SS_B_单词分析 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
char[] ch = sc.nextLine().toCharArray();
int[] r = new int[26];
for(int i=0; i<ch.length; ++i) {
++ r[ch[i]-'a'];
}
char res = 'a';
int max = Integer.MIN_VALUE;
for(int i=0; i<r.length; ++i) {
if(r[i]>max) {
res = (char)('a'+i);
max = r[i];
}
}
System.out.println(res);
System.out.println(max);
}
}
解题思路:
试题 H: 数字三角形
时间限制: 1.0s 内存限制: 512.0MB 本题总分:20 分
- 【问题描述】
上图给出了一个数字三角形。从三角形的顶部到底部有很多条不同的路径。 对于每条路径,把路径上面的数加起来可以得到一个和,你的任务就是找到最 大的和。
路径上的每一步只能从一个数走到下一层和它最近的左边的那个数或者右 边的那个数。此外,向左下走的次数与向右下走的次数相差不能超过 1。
输入的第一行包含一个整数 N (1 < N ≤ 100),表示三角形的行数。下面的 N 行给出数字三角形。数字三角形上的数都是 0 至 100 之间的整数。
输出一个整数,表示答案。
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
27
个人代码:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
public class _11_SS_B_数字三角形 {
public static void main(String[] args) throws IOException {
InputReader sc = new InputReader(System.in);
int n = sc.nextInt();
int[][] r = new int[n][n];
for(int i=0; i<n; ++i) {
for(int j=0; j<=i; ++j) {
r[i][j] = sc.nextInt();
}
}
int[][][] dp = new int[n][n][n+1];
dp[0][0][0] = r[0][0];
for(int i=0; i<n-1; ++i) {
for(int j=0; j<=i; ++j) {
for(int k=0; k<n; ++k) {
if(dp[i][j][k] != 0) {
dp[i+1][j][k] = Math.max(dp[i+1][j][k], dp[i][j][k]+r[i+1][j]);
dp[i+1][j+1][k+1] = Math.max(dp[i+1][j+1][k+1], dp[i][j][k]+r[i+1][j+1]);
}
}
}
}
int res = Integer.MIN_VALUE;
boolean ping = (n%2 != 0);
for(int i=0; i<n; ++i) {
res = Math.max(res, dp[n-1][i][n/2]);
if(ping) {
res = Math.max(res, dp[n-1][i][(n/2)+1]);
}
}
System.out.println(res);
}
static class InputReader {
StreamTokenizer tokenizer;
public InputReader(InputStream stream) {
tokenizer = new StreamTokenizer(new BufferedReader(new InputStreamReader(stream)));
tokenizer.ordinaryChars(33, 126);
tokenizer.wordChars(33, 126);
}
public String next() throws IOException {
tokenizer.nextToken();
return tokenizer.sval;
}
public int nextInt() throws IOException {
return Integer.parseInt(next());
}
}
}
//我还是太菜了,这是一个大佬的写法
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[][] r = new int[n+1][n+1];
for(int i=1; i<=n; ++i) {
for (int j = 1; j <= i; ++j) {
r[i][j] = sc.nextInt();
r[i][j] += Math.max(r[i - 1][j - 1], r[i - 1][j]);
}
}
System.out.println(n%2==1?r[n][n/2+1]:Math.max(r[n][n/2], r[n][n/2+1]));
}
}
解题思路:
试题 I: 子串分值和
时间限制: 3.0s 内存限制: 512.0MB 本题总分:25 分
对于一个字符串 S,我们定义 S 的分值 f(S) 为 S 中出现的不同的字符个 数。例如 f(”aba”) = 2,f(”abc”) = 3, f(”aaa”) = 1。 现在给定一个字符串 S[0…n−1](长度为 n),请你计算对于所有 S 的非空 子串 S[i…j](0≤i≤ j < n),f(S[i…j]) 的和是多少。
输入一行包含一个由小写字母组成的字符串 S。
输出一个整数表示答案。
ababc
28
子串 f值
a 1
ab 2
aba 2
abab 2
ababc 3
b 1
ba 2
bab 2
babc 3
a 1
ab 2
abc 3
b 1
bc 2
c 1
对于 20% 的评测用例,1≤n≤10;
对于 40% 的评测用例,1≤n≤100;
对于 50% 的评测用例,1≤n≤1000;
对于 60% 的评测用例,1≤n≤10000;
对于所有评测用例,1≤n≤100000。
个人代码:
//这种写法简单,但只能拿到小部分的分
import java.util.Arrays;
import java.util.Scanner;
public class _11_SS_B_子串分值和 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
char[] ch = sc.nextLine().toCharArray();
boolean[] vis = new boolean[26];
int size = 0;
long res = 0;
for(int i=0; i<ch.length; ++i) {
Arrays.fill(vis, false);
size = 0;
for(int j=i; j<ch.length; ++j) {
if(!vis[ch[j]-'a']) {
++ size;
vis[ch[j]-'a'] = true;
}
res += size;
}
}
System.out.println(res);
}
}
//这种写法复杂度较低
import java.util.Scanner;
public class _11_SS_B_子串分值和 {
static char[] ch;
static int[][] vis;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
ch = sc.nextLine().toCharArray();
vis = new int[26][ch.length];
vis[ch[0]-'a'][0] = 1;
for(int i=1; i<ch.length; ++i) {
for(int j=0; j<26; ++j)
vis[j][i] = vis[j][i-1];
vis[ch[i]-'a'][i] = i+1;
}
long res = 0;
for(int i=0; i<ch.length; ++i)
for(int j=0; j<26; ++j)
res += vis[j][i];
System.out.println(res);
}
}
解题思路:
试题 J: 装饰珠
时间限制: 5.0s 内存限制: 512.0MB 本题总分:25 分
在怪物猎人这一款游戏中,玩家可以通过给装备镶嵌不同的装饰珠来获取
相应的技能,以提升自己的战斗能力。
已知猎人身上一共有 6 66 件装备,每件装备可能有若干个装饰孔,每个装饰
孔有各自的等级,可以镶嵌一颗小于等于自身等级的装饰珠 (也可以选择不镶
嵌)。
装饰珠有M种,编号1至M,分别对应M 种技能,第i种装饰珠的等级
为Li,只能镶嵌在等级大于等于Li的装饰孔中。
对第i种技能来说,当装备相应技能的装饰珠数量达到Ki个时,会产生Wi(Ki) 的价值。镶嵌同类技能的数量越多,产生的价值越大,即Wi(Ki − 1) < Wi(Ki) 。但每个技能都有上限Pi(1 ≤ P i ≤ 7) ,当装备的珠子数量超过Pi时,只会产生Wi(Pi) 的价值。
对于给定的装备和装饰珠数据,求解如何镶嵌装饰珠,使得 6 件装备能得
到的总价值达到最大。
输入的第1至6行,包含6件装备的描述。其中第i的第一个整数Ni表示
第i件装备的装饰孔数量。后面紧接着Ni个整数,分别表示该装备上每个装饰
孔的等级L(1 ≤ L ≤ 4) 。
第7行包含一个正整数M,表示装饰珠 (技能) 种类数量。
第8至 M + 7行,每行描述一种装饰珠 (技能) 的情况。每行的前两个整数Lj(1 ≤ Lj ≤ 4)和Pj(1 ≤ Pi ≤ 7)分别表示第j种装饰珠的等级和上限。接下来Pj个整数,其中第k个数表示装备该中装饰珠数量为k时的价值 Wj(k)。
输出一行包含一个整数,表示能够得到的最大价值。
1 1
2 1 2
1 1
2 2 2
1 1
1 3
3
1 5 1 2 3 5 8
2 4 2 4 8 15
3 2 5 10
20
按照如下方式镶嵌珠子得到最大价值 18,括号内表示镶嵌的装饰珠的种类编号:
1: (1)
2: (1) (2)
3: (1)
4: (2) (2)
5: (1)
6: (2)
4 颗技能 1 装饰珠,4 颗技能 2 装饰珠 W1(4) + W2(4) = 5 + 15 = 20。
对于 30% 的评测用例,1 ≤ Ni ≤ 10, 1 ≤ M ≤ 20, 1 ≤ Wj(k) ≤ 500;
对于所有评测用例,1 ≤ Ni ≤ 50, 1 ≤ M ≤ 10000, 1 ≤ Wj(k) ≤ 10000。