前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >第十一届蓝桥杯大赛个人赛校内选拔(软件类)题解

第十一届蓝桥杯大赛个人赛校内选拔(软件类)题解

作者头像
静谧星空TEL
发布2021-04-27 14:33:12
9560
发布2021-04-27 14:33:12
举报

第十一届蓝桥杯大赛个人赛校内选拔(软件类)题目:https://cloud.tencent.com/developer/article/1818701

第十一届蓝桥杯大赛个人赛校内选拔(软件类)题解:https://cloud.tencent.com/developer/article/1818705

1.15.125GB

【问题描述】 在计算机存储中,15.125GB是多少MB? 【答案提交】 这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。 

代码语言:javascript
复制
15488

2.约数个数

【问题描述】 1200000有多少个约数(只计算正约数)。 【答案提交】 这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

代码语言:javascript
复制
public class _11_02 {

    public static void main(String[] args) {
        int n = core(1200000);
        System.out.println(n);
    }
    public static int core(int f) {
        int n = 0;
        for(int i=1;i<=f;i++) {
            if(f%i==0) ++n;
        }
        return n;
    }
}

3.叶结点数

【问题描述】 一棵包含有2019个结点的二叉树,最多包含多少个叶结点? 【答案提交】 这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

方法一 

找规律

用画图工具把二叉树画出来

将结点数和二叉树分别列出来后

1    1

3    2

4    3

5    3

6    3

7    4

8    4

9    5

10    5

11    6

12    6

13    7

14    7

15    8

16    8

不难发现

当结点数为偶数时,叶子结点数等于结点数的一半

当结点数为奇数时,叶子结点数等于结点数的一半(取整后)加1

2019为奇数,故答案为 

代码语言:javascript
复制
2019/2 + 1 = 1010

方法二

给出固定结点数,求二叉树的叶子结点的最大值

问题可转换为已知结点数求满二叉树或者完全二叉树

根据满二叉树的性质,设二叉树的深度为 n

第 n 层有 2^(n-1) 个结点,二叉树一共有 (2^n)-1 个结点

代码语言:javascript
复制
public class _11_03 {

    public static void main(String[] args) {
        int result = core(2019);
        System.out.println(result);
    }

    /**
     * 已知叶二叉树的结点数,求最大叶子结点数
     */
    public static int core(int f) {
        if(f<2) return f;
        // f表示二叉树的结点数
        int n = 0;  // n表示二叉树的高度
        int an = 0; // an表示第n层完全二叉树的叶子结点数
        int m = 0;  // an表示n层完全二叉树的结点数
        while (f > m) {
            an = (int) Math.pow(2, n - 1);
            m = (int) Math.pow(2, n) - 1;
//            System.out.println("第 " + n + " 层有 " + m + " 个结点, " + an + " 个叶子结点, " + (m - an) + " 个非叶子结点");
            ++n;
        }   --n;
        int b = f-(m-an);   // 当结点数为f时,最底层的叶子结点数
        int b0 = b%2==0 ? b/2 : b/2+1;
        int c = (int) Math.pow(2, n - 1 -1) - b0;     // 倒数第二层的叶子结点数 = 倒数第二层结点数 - 底层叶子结点数的上层结点数
        System.out.println("拥有 "+f+" 个结点的二叉树,有 "+b+" 个叶子结点在第 "+n+" 层,"+c+" 个叶子结点在第 "+(n-1)+" 层");
        int result = b + c;
        return result;
    }
}

运行结果

第 0 层有 0 个结点, 0 个叶子结点, 0 个非叶子结点

第 1 层有 1 个结点, 1 个叶子结点, 0 个非叶子结点

第 2 层有 3 个结点, 2 个叶子结点, 1 个非叶子结点

第 3 层有 7 个结点, 4 个叶子结点, 3 个非叶子结点

第 4 层有 15 个结点, 8 个叶子结点, 7 个非叶子结点

第 5 层有 31 个结点, 16 个叶子结点, 15 个非叶子结点

第 6 层有 63 个结点, 32 个叶子结点, 31 个非叶子结点

第 7 层有 127 个结点, 64 个叶子结点, 63 个非叶子结点

第 8 层有 255 个结点, 128 个叶子结点, 127 个非叶子结点

第 9 层有 511 个结点, 256 个叶子结点, 255 个非叶子结点

第 10 层有 1023 个结点, 512 个叶子结点, 511 个非叶子结点

第 11 层有 2047 个结点, 1024 个叶子结点, 1023 个非叶子结点

拥有 2019 个结点的二叉树,有 996 个叶子结点在第 11 层,14 个叶子结点在第 10 层

1010  

图形分析

假设二叉树是完全二叉树,有最后一层的结点数为1024,倒数第二层结点数为512

由此可见,2019个结点的二叉树在最底层的叶子节点数为2048-2019=996

则有倒数第二层的叶子结点数等于此层结点数减去底层叶子结点数的父节点数512-498=14

最终结果

996+14=1010 

4.数字9

【问题描述】 在1至2019中,有多少个数的数位中包含数字9? 注意,有的数中的数位中包含多个9,这个数只算一次。例如,1999这个数包含数字9,在计算只是算一个数。 【答案提交】 这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

代码语言:javascript
复制
public class _11_04 {

    public static void main(String[] args) {
        int n = core(2019);
        System.out.println(n);
    }
    public static int core(int f) {
        int n = 0;
        for(int i=1;i<=f;i++) {
            if(judge(i)) {
                ++n;
            }
        }
        return n;
    }
    public static boolean judge(int n) {
        while(n > 0) {
            if(n%10 == 9) return true;
            n/=10;
        }
        return false;
    }
}

最终结果

544

5.数位递增的数

【问题描述】 一个正整数如果任何一个数位不大于右边相邻的数位,则称为一个数位递增的数,例如1135是一个数位递增的数,而1024不是一个数位递增的数。 给定正整数 n,请问在整数 1 至 n 中有多少个数位递增的数? 【输入格式】 输入的第一行包含一个整数 n。 【输出格式】 输出一行包含一个整数,表示答案。 【样例输入】 30 【样例输出】 26 【评测用例规模与约定】 对于 40% 的评测用例,1 <= n <= 1000。 对于 80% 的评测用例,1 <= n <= 100000。 对于所有评测用例,1 <= n <= 1000000。

代码语言:javascript
复制
import java.util.Scanner;

/**
 * 5.数位递增的数
 */
public class _11_05 {
    static Scanner sc = new Scanner(System.in);
    static int n = sc.nextInt();

    public static void main(String[] args) {
        int result = core(n);
        System.out.println(result);
    }

    public static int core(int n) {
        int result = 0;
        for(int i=1;i<=n;++i) {
            if(judge(i)) {
                ++result;
            }
        } return result;
    }

    /**
     * 判断是否数位递增
     */
    public static boolean judge(int n) {
        if(n < 10) return true;
        int digit = 0;  // n的位数
        int m = n;
        while(m/10 > 0) {
            m/=10;
            ++digit;
        } ++digit;
//        System.out.println("digit "+digit);
        int left = 0, right = 10;
        while(digit-- > 0) {
            left = n%10;
            if(left > right) return false;
            right = left;
            n/=10;
        }
        return true;
    }

}

运行结果

代码语言:javascript
复制
300
135

6.递增三元组

【问题描述】 在数列 a1, a2, ..., an 中,如果对于下标 i, j, k 满足 0 给定一个数列,请问数列中有多少个元素可能是递增三元组的中心。 【输入格式】 输入的第一行包含一个整数 n。 第二行包含 n 个整数 a1, a2, ..., an,相邻的整数间用空格分隔,表示给定的数列。 【输出格式】 输出一行包含一个整数,表示答案。 【样例输入】 5 1 2 5 3 5 【样例输出】 2 【样例说明】 a2 和 a4 可能是三元组的中心。 【评测用例规模与约定】 对于 50% 的评测用例,2 <= n <= 100,0 <= 数列中的数 <= 1000。 对于所有评测用例,2 <= n <= 1000,0 <= 数列中的数 <= 10000。

代码语言:javascript
复制
import java.util.Arrays;
import java.util.Scanner;

/**
 * 6.递增三元组
 */
public class _11_06 {

    static Scanner sc = new Scanner(System.in);
    static int n = sc.nextInt();
    static int[] A = new int[n];

    static {
        for (int i=0;i max ? result : max;
        }
        return max;
    }

}

运行结果

代码语言:javascript
复制
16
1 2 5 3 5 0 1 2 1 2 1 2 1 2 1 2
5

7.音节判断

【问题描述】 小明对类似于 hello 这种单词非常感兴趣,这种单词可以正好分为四段,第一段由一个或多个辅音字母组成,第二段由一个或多个元音字母组成,第三段由一个或多个辅音字母组成,第四段由一个或多个元音字母组成。 给定一个单词,请判断这个单词是否也是这种单词,如果是请输出yes,否则请输出no。 元音字母包括 a, e, i, o, u,共五个,其他均为辅音字母。 【输入格式】 输入一行,包含一个单词,单词中只包含小写英文字母。 【输出格式】 输出答案,或者为yes,或者为no。 【样例输入】 lanqiao 【样例输出】 yes 【样例输入】 world 【样例输出】 no 【评测用例规模与约定】 对于所有评测用例,单词中的字母个数不超过100。

状态标记法

将四个阶段的每个状态用数字a1-a4表示出来

初始状态为0,进入状态则为1,状态结束为2

直到第四个状态a4=1并且后续不会再有状态变化则为符合条件

代码语言:javascript
复制
import java.util.Scanner;

/**
 * 7.音节判断
 */
public class _11_07 {

    static Scanner sc = new Scanner(System.in);
    static String word = sc.next();

    public static void main(String[] args) {
        String result = core(word);
        System.out.println(result);
    }

    public static String core(String word) {
        char[] chars = word.toCharArray();
        if(chars.length<4) return "no";     // 单词小于四个字母的不符合
        if(isVowel(chars[0])) return "no";  // 第一个是元音字母的不符合
        int a1=0,a2=0,a3=0,a4=0;            // 0:初始状态  1:当前状态   2:结束状态
        for(int i=0;i

运行结果 ccccccccccccccccccccccccccccoooooooooooooooooooooooooooooobbbbbbbbbbbbbbbbbbbbbbbbbbiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii yes ccccccccccccccccccccccccccccoooooooooooooooooooooooooooooobbbbbbbbbbbbbbbbbbbbbbbbbbiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiivvvv no

8.长草

代码语言:javascript
复制
 【问题描述】
 小明有一块空地,他将这块空地划分为 n 行 m 列的小块,每行和每列的长度都为 1。
 小明选了其中的一些小块空地,种上了草,其他小块仍然保持是空地。
 这些草长得很快,每个月,草都会向外长出一些,如果一个小块种了草,则它将向自己的上、下、左、右四小块空地扩展,这四小块空地都将变为有草的小块。
 请告诉小明,k 个月后空地上哪些地方有草。
 【输入格式】
 输入的第一行包含两个整数 n, m。
 接下来 n 行,每行包含 m 个字母,表示初始的空地状态,字母之间没有空格。如果为小数点,表示为空地,如果字母为 g,表示种了草。
 接下来包含一个整数 k。
 【输出格式】
 输出 n 行,每行包含 m 个字母,表示 k 个月后空地的状态。如果为小数点,表示为空地,如果字母为 g,表示长了草。
 【样例输入】
 4 5
 .g...
 .....
 ..g..
 .....
 2
 【样例输出】
 gggg.
 gggg.
 ggggg
 .ggg.
 【评测用例规模与约定】
 对于 30% 的评测用例,2 <= n, m <= 20。
 对于 70% 的评测用例,2 <= n, m <= 100。
 对于所有评测用例,2 <= n, m <= 1000,1 <= k <= 1000。
 
代码语言:javascript
复制
import java.util.Arrays;
import java.util.Scanner;

/**
 * 8.长草
 */
public class _11_08 {

    static Scanner sc = new Scanner(System.in);
    static int n = sc.nextInt();
    static int m = sc.nextInt();
    static char[][] chars = new char[n][m];
    static {
        char[] str;
        for(int i=0;i= k) return chars;     // 递归出口,已经长了k个月
        char[][] copy = new char[n][m];
        // 二维数组拷贝
        for (int i=0;i=0) chars[i-1][j] = 'g';
                    if(j-1>=0) chars[i][j-1] = 'g';
                    if(i+1

运行结果

4 5

.g...

.....

..g..

.....

2

gggg.

gggg.

ggggg

.ggg.

9.序列计数

【问题描述】 小明想知道,满足以下条件的正整数序列的数量: 1. 第一项为 n; 2. 第二项不超过 n; 3. 从第三项开始,每一项小于前两项的差的绝对值。 请计算,对于给定的 n,有多少种满足条件的序列。 【输入格式】 输入一行包含一个整数 n。 【输出格式】 输出一个整数,表示答案。答案可能很大,请输出答案除以10000的余数。 【样例输入】 4 【样例输出】 7 【样例说明】 以下是满足条件的序列: 4 1 4 1 1 4 1 2 4 2 4 2 1 4 3 4 4 【评测用例规模与约定】 对于 20% 的评测用例,1 <= n <= 5; 对于 50% 的评测用例,1 <= n <= 10; 对于 80% 的评测用例,1 <= n <= 100; 对于所有评测用例,1 <= n <= 1000。

方法一 

代码语言:javascript
复制
import java.util.HashSet;
import java.util.Scanner;

/**
 * 9.序列计数
 */
public class _11_09 {

    static Scanner sc = new Scanner(System.in);
    static int n = sc.nextInt();
    static HashSet set = new HashSet<>();

    public static void main(String[] args) {
        core(n);
        foreachSet(set);
        System.out.println(set.size());
    }

    public static void core(int n) {
        // 第二个数小于等于n
        for(int i=1;i<=n;i++) {
            int n1 = n, n2 = i; // 第一列为n,第二列为i
            String sequence = n1 + " " + n2;
            set.add(sequence);	// 初始化序列 n1=n n2<=n
            dfs(sequence,n1,n2);	// 递归循环
        }
    }

    public static void dfs(String sequence,int n1,int n2) {
        if(Math.abs(n1-n2)<=1) return;
        for(int next=1;next set) {
        set.forEach( x -> System.out.println(x));
    }

}

虽然可以直观地显示序列,但是很耗费内存

 运行结果

代码语言:javascript
复制
5
5 1 3 1 1
5 1 2
5 2 1
5 1 3
5 2 2
5 3 1
5 1
5 2
5 3
5 3 1 1
5 4
5 5
5 1 1
5 1 3 1
14

方法二

代码语言:javascript
复制
import java.util.Scanner;

/**
 * 9.序列计数——
 */
public class _11_09_ {

    static Scanner sc = new Scanner(System.in);
    static int n = sc.nextInt();
    static int count = 0;

    public static void main(String[] args) {
        core(n);
        System.out.println(count%10000);
    }

    public static void core(int n) {
        // 第二个数小于等于n
        for(int i=1;i<=n;i++) {
            count++;
            dfs(n,i);	// 递归循环
        }
    }

    public static void dfs(int n1,int n2) {
        if(Math.abs(n1-n2)<=1) return;
        for(int next=1;next

虽然简化了,但是随着数值变大,还是会出现超时和栈溢出的问题。

优化思路一:用树或链表代替递归方法实现递归回溯。

优化思路二:随着数值越大会出现很多重复计算的序列,需要记忆计算过的序列。

运行结果 

20

3277

10.晚会节目单

【问题描述】 小明要组织一台晚会,总共准备了 n 个节目。然后晚会的时间有限,他只能最终选择其中的 m 个节目。 这 n 个节目是按照小明设想的顺序给定的,顺序不能改变。 小明发现,观众对于晚上的喜欢程度与前几个节目的好看程度有非常大的关系,他希望选出的第一个节目尽可能好看,在此前提下希望第二个节目尽可能好看,依次类推。 小明给每个节目定义了一个好看值,请你帮助小明选择出 m 个节目,满足他的要求。 【输入格式】 输入的第一行包含两个整数 n, m ,表示节目的数量和要选择的数量。 第二行包含 n 个整数,依次为每个节目的好看值。 【输出格式】 输出一行包含 m 个整数,为选出的节目的好看值。 【样例输入】 5 3 3 1 2 5 4 【样例输出】 3 5 4 【样例说明】 选择了第1, 4, 5个节目。 【评测用例规模与约定】 对于 30% 的评测用例,1 <= n <= 20; 对于 60% 的评测用例,1 <= n <= 100; 对于所有评测用例,1 <= n <= 100000,0 <= 节目的好看值 <= 100000。

错误案例

代码语言:javascript
复制
import java.util.Arrays;
import java.util.Scanner;

/**
 * 10.晚会节目单
 */
public class _11_10 {

    static Scanner sc = new Scanner(System.in);
    static int n = sc.nextInt();
    static int m = sc.nextInt();
    static int[] A = new int[n];
    static {
        for(int i=0;i<n;i++) {
            A[i] = sc.nextInt();
        }
    }
    public static void main(String[] args) {
        f();
    }
 
    public static void f() {
        Arrays.sort(A);
        for(int i=n-m;i<n-1;i++) {
            System.out.print(A[i]+" ");
        }System.out.print(A[n-1]);
    }
}

错误结果

100 30 1 5 6 8 3 6 4 7 9 8 2 4 11 5 32 0 15 4 8 7 625 25 13 54 13 5 4 2 5 9 8 7 42 3 6 4 64 84 864 456 46 4 456 45 4564 56 4657 87 41 654 416 574 12 634 896 413 4186 4 16 57 941 6 74 894 1034 13 21 5 64 023 1 657 489 41 30 5 489 40 32 4 10 32 4 610 324 10 32 48 9 64 1 32 48 641 2048 678 10 23 156 41 02 4531 021 1 5 6 8 3 6 4 7 9 8 2 4 11 5 32 0 15 4 8 7 625 25 13 54 13 5 4 2 5 9 8 7 42 3 6 464 84 864 456 46 4 456 45 4564 56 1 5 6 8 3 6 4 7 9 8 2 4 11 5 32 0 15 4 8 7 625 25 13 54 13 5 4 2 5 9 8 7 42 3 6 4 64 84 864 456 46 4 456 45 4564 56 4657 87 41 654 416 574 12 634 896 413 4186 4 16 57 941 6 74 894 1034 13 21 5 64 023 1 657 489 41 30 5 489 40 32 4 10 32 4 610 324 10 32 48 9 64 1 32 48 641 2048 678 10 23 156 41 02 4531 021 1 5 6 8 3 6 4 7 9 8 2 4 11 5 32 0 15 4 8 7 625 25 13 54 13 5 4 2 5 9 8 7 42 3 6 464 84 864 456 46 4 456 45 4564 56 64 64 74 84 87 156 324 413 416 456 456 489 489 574 610 625 634 641 654 657 678 864 894 896 941 1034 2048 4186 4564 4657

正确案例

代码语言:javascript
复制
import java.util.*;
 
/**
 * 10.晚会节目单
 * 解题思路:
 * 1、如果直接对n个数进行排序,输出的结果不能保证节目的顺序
 * 2、使用栈在输入时插入排序,栈存储数组A的索引,取最大的m个值
 * 3、最后对数组A的索引重新排序即可还原节目顺序输出前m大的值
 */
public class _11_10_ {
 
    static Scanner sc = new Scanner(System.in);
    static int n = sc.nextInt();
    static int m = sc.nextInt();
 
    public static void main(String[] args) {
        f();
    }
 
    public static void f() {
        Stack<Integer> stack = new Stack<>();
        int[] A = new int[n];   // 存节目好看值
        int[] B = new int[m];   // 数组A的索引
        A[0]=sc.nextInt();
        stack.add(0);   // 第一个值直接插入
        for(int i=1;i<n;i++) {
            A[i] = sc.nextInt();
            // 如果当前值大于最后一个则直接添加
            if(A[i] < A[stack.firstElement()]) { stack.insertElementAt(i,0); continue; }
            if(A[i] > A[stack.lastElement()]) { stack.add(i); continue; }
            for(int j=1;j<i;j++) {      // 从头遍历栈,直到小于时插入
                if(A[i] < A[stack.get(j)]) { stack.insertElementAt(i, j); break; }
            }
        }
        if(n == m) { stack.forEach(i -> System.out.print(A[i]+" ")); return; }
        for(int i=n-m,j=0;i<n;i++,j++)  {
            B[j] = stack.get(i);    // 数组B保存A数组的索引
        } Arrays.sort(B); // A数组索引从小到大排序
        for(int i=0;i<m;i++) System.out.print(A[B[i]]+" "); // 输出结果
    }
 
}

最终结果

10 5

12 74 100 15 54 35 86 63 24 46

74 100 54 86 63

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-01-02 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.15.125GB
  • 2.约数个数
  • 3.叶结点数
    • 方法一 
      • 方法二
      • 4.数字9
      • 5.数位递增的数
      • 6.递增三元组
      • 7.音节判断
      • 8.长草
      • 9.序列计数
        • 方法一 
          • 方法二
          • 10.晚会节目单
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档