2020年第十一届蓝桥杯JavaC组(十月场)真题解析

相关题目:

2016年第七届蓝桥杯真题解析JavaB组

2016年第七届蓝桥杯真题解析JavaC组

2017年第八届蓝桥杯真题解析JavaB组

2017年第八届蓝桥杯真题解析JavaC组

2018年第九届蓝桥杯真题解析JavaB组

2018年第九届蓝桥杯真题解析JavaC组

2019年第十届蓝桥杯真题解析JavaB组

2019年第十届蓝桥杯真题解析JavaC组

2020年第十一届蓝桥杯JavaB组(七月场)真题解析

2020年第十一届蓝桥杯JavaC组(七月场)真题解析

2020年第十一届蓝桥杯JavaB组(十月场)真题解析

2020年第十一届蓝桥杯JavaC组(十月场)真题解析

A 约数个数

【问题描述】

对于一个整数,能整除这个整数的数称为这个数的约数。
例如:1, 2, 3, 6 都是 6 的约数。
请问 78120 有多少个约数。

【答案提交】

思路:直接遍历判断

代码:


public class 约数个数 {
    public static void main(String[] args) {
        int ans = 0;
        for (int i = 1; i <= 78120; i++) {
            if (78120 % i == 0) ans++;
        }
        System.out.println(ans);
    }
}

答案 :96

B 寻找2020

题目:
小蓝有一个数字矩阵,里面只包含数字 0 和 2。小蓝很喜欢 2020,他想找
到这个数字矩阵中有多少个 2020 。
小蓝只关注三种构成 2020 的方式:

1.同一行里面连续四个字符从左到右构成 2020。
2.同一列里面连续四个字符从上到下构成 2020。
3.在一条从左上到右下的斜线上连续四个字符,从左上到右下构成 2020。

例如,对于下面的矩阵:

220000
000000
002202
000000
000022
002020

一共有 5 个 2020。其中 1 个是在同一行里的,1 个是在同一列里的,3 个
是斜线上的。
小蓝的矩阵比上面的矩阵要大,由于太大了,他只好将这个矩阵放在了一
个文件里面,在试题目录下有一个文件 2020.txt,里面给出了小蓝的矩阵。
请帮助小蓝确定在他的矩阵中有多少个 2020。
(测试数据太大了我就不放这里了,我放个图片大概是这样子的)
在这里插入图片描述思路:

1.暴力搜之前,要知道它每行每列的长度,一个简单的方法
从最左上角把鼠标按往一直往最右下角拉,记事本右下角
就会自己显示,我考试的时候没想起来这样做,吐血。

2.然后就是搜索,从左往右从上往下,只要找到一个"2",就
可以开始深搜,分别找每个'2'的四个方向上下左右,左上到右下,
每当有一个方向上是符合条件的就count++;

代码:

import java.util.Scanner;
public class 寻找2020 {
    static int count=0;
   static char [][]arr2=new char[400][400];
   static char []arr3={'2','0','2','0'};
    public static void main(String[] args) {
        Scanner input=new Scanner(System.in);
        String []arr=new String[301];
        for(int i=0;i<300;i++){
            arr[i]=input.next();
        }
        for(int i=0;i<300;i++){
            arr2[i]=arr[i].toCharArray();
        }
        for(int i=0;i<300;i++){
            for(int j=0;j<300;j++){
                if(arr2[i][j]=='2'){
                    dfs(i,j);
                }
            }
        }
        System.out.println(count);
    }
    public static void dfs(int x,int y){
        int flag=1;//用来判断是否满足条件
        //找从左往右
        for(int i=1;i<=3;i++){
            //越界了就说明这个方向肯定不行
            if(y+i<0||y+i>=300)
            {
                flag=0;
                break;
            }
            if(arr2[x][y+i]!=arr3[i]){
                flag=0;
                break;
            }
        }
        if(flag==1)
            count++;
        //每判断一次要更新flag=1,以免对下一次判断造成误解
        flag=1;
        //从上到下
        for(int i=1;i<=3;i++){
            if(x+i<0||x+i>=300)
            {
                flag=0;
                break;
            }
            if(arr2[x+i][y]!=arr3[i]) {
                flag=0;
                break;
            }
        }
        if(flag==1 )
            count++;
        flag=1;
        //左上到右下

        for(int i=1;i<=3;i++){
            if((y+i<0||y+i>=300)||(x+i<0&&x+i>=300)){
                flag=0;
                break;
            }
            if(arr2[i+x][y+i]!=arr3[i]){
                flag=0;
                break;
            }
        }
        if(flag==1)
            count++;
    }
}

答案:

16520

试题 C: 跑步锻炼

本题总分:10 分

【问题描述】

小蓝每天都锻炼身体。
正常情况下,小蓝每天跑 1 千米。如果某天是周一或者月初(1 日),为了激励自己,小蓝要跑 2 千米。如果同时是周一或月初,小蓝也是跑 2 千米。
小蓝跑步已经坚持了很长时间,从 2000 年 1 月 1 日周六(含)到 2020 年10 月 1 日周四(含)。请问这段时间小蓝总共跑步多少千米?

思路:

先要把判断是不是闰年,然后2020年的时候要特判一下,因为
2020年只到101日,判断星期几的时候只要取余就好了一月一号
是星期六 那么对应的就是 2号对应星期天,3号对应星期一,4号
对应星期二......天数下标从0开始
public class 跑步锻炼 {
    static int []week={6,7,1,2,3,4,5};//一月一号星期六,依次往后推
    static int []months={0,31,28,31,30,31,30,31,31,30,31,30,31};
    public static void main(String[] args) {
        int ans=0;
        int sumday=0;//总天数.用来判断星期几
        //年
        for(int year=2000;year<=2020;year++){

            //判断是否是闰年
            if(!check(year)){
                //不是闰年就按正常的来
                for(int month=1;month<=12;month++){
                    for(int day=1;day<=months[month];day++){
                        if(day==1||week[sumday%7]==1)
                            ans+=2;
                        else ans++;
                        sumday++;
                    }
                }
            }
            //是闰年
            else {
                if(year==2020){//特判一下2020年因为今年就10个月跑
                    for (int month = 1; month <= 10; month++) {
                        if(month==10){
                            ans+=2;
                            break;
                        }
                        if (month != 2&&month<10) {
                            for (int day = 1; day <= months[month]; day++) {
                                if (day == 1 || week[sumday % 7] == 1)
                                    ans += 2;
                                else ans++;
                                sumday++;
                            }
                        }
                        else if(month==2){
                            for (int day = 1; day <= 29; day++) {
                                if (day == 1 || week[sumday % 7] == 1)
                                    ans += 2;
                                else ans++;
                                sumday++;
                            }
                        }
                    }
                }
               else {
                    for (int month = 1; month <= 12; month++) {
                        if (month != 2) {
                            for (int day = 1; day <= months[month]; day++) {
                                if (day == 1 || week[sumday % 7] == 1)
                                    ans += 2;
                                else ans++;
                                sumday++;
                            }
                        } else {
                            for (int day = 1; day <= 29; day++) {
                                if (day == 1 || week[sumday % 7] == 1)
                                    ans += 2;
                                else ans++;
                                sumday++;
                            }
                        }
                    }

                }

            }

        }
        System.out.println(ans);
    }
    static boolean check(int year){
        if((year%4==0&&year%100!=0)||year%400==0){
            return true;
        }
        else return false;
    }
}

答案:8879

D 平面分割

本题总分:10 分

【问题描述】

20 个圆和 20 条直线最多能把平面分成多少个部分?

抱歉能力有限写不来

D 七段码

题目:

小蓝要用七段码数码管来表示一种特殊的文字。

上图给出了七段码数码管的一个图示,数码管中一共有 7 段可以发光的二
极管,分别标记为 a, b, c, d, e, f, g。

小蓝要选择一部分二极管(至少要有一个)发光来表达字符。在设计字符
的表达时,要求所有发光的二极管是连成一片的。

例如:b 发光,其他二极管不发光可以用来表达一种字符。
例如:c 发光,其他二极管不发光可以用来表达一种字符。
这种方案与上一行的方案可以用来表示不同的字符,尽管看上去比较相似。

例如:a, b, c, d, e 发光,f, g 不发光可以用来表达一种字符。
例如:b, f 发光,其他二极管不发光则不能用来表达一种字符,因为发光
的二极管没有连成一片。

请问,小蓝可以用七段码数码管表达多少种不同的字符?

思路:

大体思路是这样
1.要求多少种不同的表达式,换一种说法a~g所有的灯排成一行,放进一个
一维数组(递归实现指数型枚举),每次从中选取人n个灯,选到的灯变亮,
不选的不亮,这样就把所有情况都包含进来,我们只需判断每一种情况是否
合法,和发则ans++;

2.为了更好的判断所有亮的灯是否联通,把原图转换成一下这种二维图
然后六个方向搜索就行了,哪六个呢:右下、左下、左上、右上、下两格、上两格;

3.注意并不是所有的灯都有以上这六种方向,看原图的灯,如果a和g这
两个灯亮了并不满足题意,因为它们不相连,因此a、g、d这个一列所搜的
时候不会有六个方向只会有四个;


在这里插入图片描述
代码:

import java.util.Scanner;
public class 七段码 {
    static int N=7;
    static int ans=0;
    static int countdeng=0;//每一次深搜时亮灯的个数

    public static void main(String[] args) {
        Scanner input=new Scanner(System.in);
        //把所有灯的情况全部判断出来,然后判断此时的情况是否合法
        //第一步深搜枚举
        int []arr=new int[8];
        int []vis=new int[8];
        dfs(arr,vis,1);

        System.out.println(ans);
    }
    static void dfs(int []arr,int []vis,int level){
        if(level>7){
            check(arr);
            return;
        }
        //一共就两种情况,一种是要当前这个灯亮,一种是不要,分别深搜就行
        vis[level]=1;
        arr[level]=1;
        dfs(vis,arr,level+1);
        vis[level]=0;
        arr[level]=0;
        dfs(vis,arr,level+1);
    }
    static void check(int []arr){
        //先把此时灯亮的情况,在表格中显示出来,如果某一个灯需要亮
        //在二维表格中它对应的数就为1;
        int [][]map=new int[6][4];
        int [][]tempmap=new int[6][4];
        //a
        map[1][2]=arr[1];
        //b
        map[2][3]=arr[2];
        //c
        map[4][3]=arr[3];
        //d
        map[5][2]=arr[4];
        //e
        map[4][1]=arr[5];
        //f
        map[2][1]=arr[6];
        //g
        map[3][2]=arr[7];

        //我们要看此时灯是否能连起来
        //可以还用深搜,先把所有的灯亮的个数记录起来
        //然后以其中一个亮点为起点,向其中六个方向深搜
        //每找到一个一个可以联通的点总的灯数就减去一
        //最后全部搜完后还剩一盏灯亮着就说明当前方案可行,反之则不行
        //找总共有多少盏灯亮着
        //所欲多次深搜要初始化
        countdeng=0;
        for(int i=1;i<=5;i++) {
            for (int j = 1; j <= 3; j++) {
                if (map[i][j] != 0)
                    countdeng++;
            }
        }
        //找到了所有灯之后,找一个亮灯的点,开始深搜
        int flag=0;//只需要找一个点深搜即可,搜一次后就全部停止
        for(int i=1;i<=5;i++){
            for(int j=1;j<=3;j++) {
                if (map[i][j] != 0) {
                    flag = 1;
                    check2(map,tempmap, i, j);
                    break;
                }
            }
            if (flag==1)
                break;
        }
        if(countdeng-1==0)
        {
        ans++;
        }
    }
    //能走的六个方向
    public static  int []xx={1,1,-1,-1,-2,2};//2和-2是因为原图中两个边上的相连也算 
                                             //转换成二维图就是加-2和加2
    public static  int []yy={-1,1,-1,1,0,0};


    static void check2(int [][]map,int [][]temp,int x,int y){
        temp[x][y]=1;//起始点也要标记下
        for(int i=0;i<6;i++){
            if(y==2&&i>=4){
                continue;
            }
            //这一步很重要,因为中间的a,g,d按原图来是不能上下跳的,这样按原图来是不连续的
            //然后就是判断是否越界,是否已经找过,是否灯亮
            int tempx=x+xx[i];
            int tempy=y+yy[i];
            //看是否越界
            if(tempx>5||tempx<1)
                continue;
            if(tempy>3||tempy<1)
                continue;
            //是否找到过
            if(temp[tempx][tempy]!=0)
                continue;
            //判断这个点是否有
            if(map[tempx][tempy]==0)
                continue;
            if (map[tempx][tempy]==1) {
                temp[tempx][tempy] = 1;
                countdeng--;
                check2(map, temp, tempx, tempy);
            }
        }
        return ;
    }

}

F: 成绩统计

时间限制: 1.0s 内存限制: 512.0MB
本题总分:15 分
【问题描述】

小蓝给学生们组织了一场考试,卷面总分为 100 分,每个学生的得分都是一个 0 到 100 的整数。
如果得分至少是 60 分,则称为及格。如果得分至少为 85 分,则称为优秀。
请计算及格率和优秀率,用百分数表示,百分号前的部分四舍五入保留整数。

【输入格式】

输入的第一行包含一个整数 n,表示考试人数。
接下来 n 行,每行包含一个 0 至 100 的整数,表示一个学生的得分。

【输出格式】

输出两行,每行一个百分数,分别表示及格率和优秀率。百分号前的部分四舍五入保留整数。


【样例输入】
7
80
92
56
74
88
100
0

【样例输出】
71%
43%

【评测用例规模与约定】

对于 50% 的评测用例,1 ≤ n ≤ 100。
对于所有评测用例,1 ≤ n ≤ 10000。

思路:用Math.round四舍五入的时候要先乘100,因为小数点后的数不需要

代码:

import java.util.Scanner;
public class 成绩统计 {
    public static void main(String[] args) {
       Scanner input=new Scanner(System.in);
        int N=input.nextInt();
        double []arr=new double[N+1];
        double hege=0;
        double better=0;
        for(int i=0;i<N;i++){
            arr[i]=input.nextDouble();
            if(arr[i]>=60)
                hege++;
            if(arr[i]>=85)
                better++;
        }

        System.out.println(Math.round((hege/N)*100)+"%");
        System.out.println(Math.round((better/N)*100)+"%");

    }
}

G 单词分析

【问题描述】:

小蓝正在学习一门神奇的语言,这门语言中的单词都是由小写英文字母组成,有些单词很长,远远超过正常英文单词的长度。小蓝学了很长时间也记不住一些单词,他准备不再完全记忆这些单词,而是根据单词中哪个字母出现得最多来分辨单词。

现在,请你帮助小蓝,给了一个单词后,帮助他找到出现最多的字母和这个字母出现的次数。

输入格式

输入一行包含一个单词,单词只由小写英文字母组成。

输出格式

输出两行,第一行包含一个英文字母,表示单词中出现得最多的字母是哪
个。如果有多个字母出现的次数相等,输出字典序最小的那个。
第二行包含一个整数,表示出现得最多的那个字母在单词中出现的次数

测试样例1

输入:

lanqiao

输出:
a
2

测试样例2

输入:
longlonglongistoolong

输出:
o
6

注意: 这个输出字典序最小的

import java.util.Scanner;
public class 单词分析 {
    public static void main(String[] args) {
        Scanner input=new Scanner(System.in);
        String a=input.next();
        char []arr=a.toCharArray();
        int max=-1;
        int  maxchar=' ';
        int []count=new int[129];
        for(int i=0;i<arr.length;i++){
            count[arr[i]]++;
        }
        for(int i=0;i<=128;i++){
            if(count[i]>max){
                max=count[i];
                maxchar=i;
            }
        }
        System.out.println((char)(maxchar));
        System.out.println(max);

    }
}

H 数字三角形

【问题分析】:
在这里插入图片描述

上图给出了一个数字三角形。从三角形的顶部到底部有很多条不同的路径。
对于每条路径,把路径上面的数加起来可以得到一个和,你的任务就是找到最大的和。
路径上的每一步只能从一个数走到下一层和它最近的左边的那个数或者右边的那个数。此外,向左下走的次数与向右下走的次数相差不能超过 1。

输入格式

输入的第一行包含一个整数 N (1 < N ≤ 100),表示三角形的行数。下面的
N 行给出数字三角形。数字三角形上的数都是 0 至 100 之间的整数

输出格式

输出一个整数,表示答案。

思路:

这题要想的一点就是`“左下走的次数与向右下走的次数相差不能超过 1”
看着两个草图就比较好理解了,只要理解的剩下的就是dp

在这里插入图片描述在这里插入图片描述代码:

import java.util.Scanner;
public class 数字三角形 {
    public static void main(String[] args) {
        Scanner input=new Scanner(System.in);
        int n=input.nextInt();
        int [][]arr=new int[n+1][n+1];
        int [][]dp=new int[n+1][n+1];
        for(int i=1;i<=n;i++){
            for(int j=1;j<=i;j++){
                arr[i][j]=input.nextInt();
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=i;j++){
              //最里面一列只能从上面下来
              if(j==1){
                  dp[i][j]=dp[i-1][j]+arr[i][j];
              }
              //每行最边上一列只能从左上角下来
              else if(i==j){
                  dp[i][j]=dp[i-1][j-1]+arr[i][j];
              }
              else {
                  dp[i][j]=Math.max(dp[i-1][j],dp[i-1][j-1])+arr[i][j];
              }
            }
        }
        if(n%2!=0){
            System.out.println(dp[n][n/2+1]);
        }
        else {
            System.out.println(Math.max(dp[n][n/2+1],dp[n][n/2]));
        }
    }
}

I: 作物杂交

时间限制: 1.0s 内存限制: 512.0MB
本题总分:25 分

【问题描述】

作物杂交是作物栽培中重要的一步。已知有 N 种作物 (编号 1 至 N ),第i 种作物从播种到成熟的时间为 Ti。作物之间两两可以进行杂交,杂交时间取两种中时间较长的一方。

如作物 A 种植时间为 5 天,作物 B 种植时间为 7 天,则 AB 杂交花费的时间为 7 天。作物杂交会产生固定的作物,新产生的作物仍然属于 N 种作物中的一种。

初始时,拥有其中 M 种作物的种子 (数量无限,可以支持多次杂交)。同时可以进行多个杂交过程。求问对于给定的目标种子,最少需要多少天能够得到。

如存在 4 种作物 ABCD,各自的成熟时间为 5 天、7 天、3 天、8 天。初始拥有 AB 两种作物的种子,目标种子为 D,

已知杂交情况为 A × B → C,A × C → D。则最短的杂交过程为:
第 1 天到第 7 天 (作物 B 的时间),A × B → C。
第 8 天到第 12 天 (作物 A 的时间),A × C → D。

花费 12 天得到作物 D 的种子。
【输入格式】

输入的第 1 行包含 4 个整数 N, M, K, T,N 表示作物种类总数 (编号 1 至N),M 表示初始拥有的作物种子类型数量,K 表示可以杂交的方案数,T 表示目标种子的编号。
第 2 行包含 N 个整数,其中第 i 个整数表示第 i 种作物的种植时间Ti(1 ≤ Ti ≤ 100)。
第 3 行包含 M 个整数,分别表示已拥有的种子类型 Kj(1 ≤ Kj ≤ M),Kj两两不同。
第 4 至 K + 3 行,每行包含 3 个整数 A, B,C,表示第 A 类作物和第 B 类作物杂交可以获得第 C 类作物的种子。
【输出格式】

输出一个整数,表示得到目标种子的最短杂交时间。

【样例输入】

6 2 4 6
5 3 4 6 4 9
1 2
1 2 3
1 3 4
2 3 5
4 5 6

【样例输出】

16

【样例说明】

第 1 天至第 5 天,将编号 1 与编号 2 的作物杂交,得到编号 3 的作物种子。
第 6 天至第 10 天,将编号 1 与编号 3 的作物杂交,得到编号 4 的作物种子。
第 6 天至第 9 天,将编号 2 与编号 3 的作物杂交,得到编号 5 的作物种子。
第 11 天至第 16 天,将编号 4 与编号 5 的作物杂交,得到编号 6 的作物种子。

总共花费 16 天。

【评测用例规模与约定】

对于所有评测用例,1 ≤ N ≤ 2000, 2 ≤ M ≤ N, 1 ≤ K ≤ 100000, 1 ≤ T ≤ N,保证目标种子一定可以通过杂交得到。

抱歉能力有限,没写来

J 子串分值和

问题描述:

对于一个字符串 S,我们定义 S 的分值 f(S ) 为 S 中恰好出现一次的字符个数。例如 f(”aba”) = 1,f(”abc”) = 3, f(”aaa”) = 0。
现在给定一个字符串 S [0…n - 1](长度为 n),请你计算对于所有 S 的非空子串 S [i… j] (0 ≤ i ≤ j < n),f(S [i… j]) 的和是多少。

输入格式

输入一行包含一个由小写字母组成的字符串 S。

输出格式

输出一个整数表示答案。

数据范围

对于 20%的评测用例,1≤n≤10;
对于 40% 的评测用例,1≤n≤100;
对于 50% 的评测用例,1≤n≤1000;
对于 60% 的评测用例,1≤n≤10000;
对于所有评测用例,1≤n≤100000。

输入样例:

ababc

输出样例:

21

样例说明

所有子串 f

值如下:

a     1
ab    2
aba   1
abab  0
ababc 1
 b    1
 ba   2
 bab  1
 babc 2
  a   1
  ab  2
  abc 3
   b  1
   bc 2
    c 1

AcWing大佬题解

  • 13
    点赞
  • 83
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值