【校选】第十一届蓝桥杯 B 组校内模拟赛

A(填) 内存计算

在计算机存储中,15.125GB 是多少 MB?

答案提交

  • 这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

* 注:看清题目,提交整数

System.out.println(15.125 * 1024);

答案:15488


B(填) 二进制数之和

两个二进制数 11110011101 和 1111101001 的和是多少?请用二进制表示,注意在提交的时候不要提交前导 0。

答案提交

  • 这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个二进制数,在提交答案时只填写这个二进制数,填写多余的内容将无法得分。

方法一:自定义 | 库函数

* 库函数,二进制转整数稍有遗忘:一定要数量使用库函数。

import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
    public static void main(String[] args) throws IOException {  
        Scanner sc = new Scanner(new BufferedInputStream(System.in));
        PrintWriter pw = new PrintWriter(System.out, true); //自动刷新
        
// 		int n1 = Integer.valueOf("11110011101", 2);
// 		int n2 = Integer.valueOf("1111101001", 2);
        int n1 = get("11110011101");
        int n2 = get("1111101001");
        
		System.out.println(n1 + " " + n2);	//1949 1001
		System.out.println(Integer.toBinaryString(n1+n2));
    }
	static int get(String s) {
		int rate = 1, res = 0;
		for (int i = s.length()-1; i >= 0; i--) {
			res +=  rate * (s.charAt(i) == '1' ? 1 : 0);
			rate *= 2;
		}
		return res;
	}
}

答案:101110000110


C(填) 约数个数

1200000 有多少个约数(只计算正约数)。

无用题。

答案:96


D(填) 叶子结点

一棵包含有 2019 个结点的二叉树,最多包含多少个叶结点?

方法一:抽象

如果没有指定树的类型,所以,最多会有 2018 个叶子结点。本题指定是二叉树:

  • 排成完全二叉树时叶子节点最多。
  • 由公式 n = n 0 + n 1 + 2 ∗ n 2 n = n0 + n1 + 2*n2 n=n0+n1+2n2 得,要使 n0 最多,n1 和 n2 必须最少。
  • 二叉树有一个性质,即 叶子节点 = 度为 2 的节点数 + 1,即 n0 = n2 + 1,而完全二叉树中 n1 = 0/1,显然 n1 = 0 时,n0 最多。
  • n 2 = ( 2019 − 1 ) / 2 = 1009 n2=(2019-1)/2=1009 n2=(20191)/2=1009,故 n 0 = 1009 + 1 = 1010 n0 = 1009 + 1 = 1010 n0=1009+1=1010

注:

  • n0:度为 0 的节点会有 0 个子结点。
    n1:度为 1 的节点会有 1 个子结点。
    n2:度为 2 的节点会有 2 个子结点。

答案:2018

参考链接:https://zhidao.baidu.com/question/37018907.html
https://zhidao.baidu.com/question/1606512639172722827.html
https://zhidao.baidu.com/question/1798769558483406667.html —> 对


E(设计) 数位递增数的个数

一个正整数如果任何一个数位不大于右边相邻的数位,则称为一个数位递增的数,例如 1135 是一个数位递增的数,而 1024 不是一个数位递增的数。给定正整数 n,请问在整数 1 至 n 中有多少个数位递增的数?

输入格式

  • 输入的第一行包含一个整数 n。

输出格式

  • 输出一行包含一个整数,表示答案。
样例输入
30
样例输出
26

评测用例规模与约定

  • 对于 40% 的评测用例,1 <= n <= 1000。
  • 对于 80% 的评测用例,1 <= n <= 100000。
  • 对于所有评测用例,1 <= n <= 1000000。

方法一:暴力

  • 错误分析:对于 80%: 1 0 5 10^5 105,即 10 w 10w 10w O ( n 2 ) O(n^2) O(n2) 的算法大概运算 ( 1 0 5 ) 2 (10^5)^2 (105)2 次,1s 时限肯定超时。
  • 正确分析:由于满足条件的数不会很多,所以暴力可以过,但是保险起见,建议采用方法二。
import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
    public static void main(String[] args) throws IOException {  
        Scanner sc = new Scanner(new BufferedInputStream(System.in));
        PrintWriter pw = new PrintWriter(System.out, true); //自动刷新
        int n = sc.nextInt();
		int count = 0;
		for (int i = 1; i <= n; i++) {
			if (check(i))
				count++;
		}
		System.out.println(count);
    }
	static boolean check(int n) {
		char[] s = (n + "").toCharArray();
		for (int i = 1; i < s.length; i++) {
			if ((s[i-1]-'0') > (s[i]-'0'))
				return false;
		}
		return true;
	}
}
复杂度分析
  • 时间复杂度: O ( n 2 ) O(n^2) O(n2)
  • 空间复杂度: O ( 1 ) O(1) O(1)

F(设计) 单词分段

小明对类似于 hello 这种单词非常感兴趣,这种单词可以正好分为四段,第一段由一个或多个辅音字母组成,第二段由一个或多个元音字母组成,第三段由一个或多个辅音字母组成,第四段由一个或多个元音字母组成。

给定一个单词,请判断这个单词是否也是这种单词,如果是请输出 yes,否则请输出 no。

元音字母包括 a, e, i, o, u,共五个,其他均为辅音字母。

输入格式

  • 输入一行,包含一个单词,单词中只包含小写英文字母。

输出格式

  • 输出答案,或者为 yes,或者为 no。
样例输入
lanqiao
样例输出
yes
样例输入
world
样例输出
no

评测用例规模与约定

  • 对于所有评测用例,单词中的字母个数不超过100。

方法一:分段统计

  • 先特判一下。
  • 分段处理,最后一定要加上 i == s.length && ...,因为可能会存在这种样例 qeqeq

* 算法的缺点:如果要判断 n 段,需要写 nwhile(...),不通用。

import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
    static int[] vowel, cons;
    public static void main(String[] args) throws IOException {  
        Scanner sc = new Scanner(new BufferedInputStream(System.in));
        PrintWriter pw = new PrintWriter(System.out, true); //自动刷新
        
		char[] s = sc.next().toCharArray();
		vowel = new int[26];	//存储元音
		cons = new int[26];	//存储辅音
		for (char c = 'a'; c <= 'z'; c++) {
			if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u')
				vowel[c-'a']++;
			else
				cons[c-'a']++;
		}
	    if (check(s))	System.out.println("yes");
        else 			System.out.println("no");
    }
    private static boolean check(char[] s) {
        if (s.length < 4)
		    return false;
        	//第一个字符非辅音或者最后一个字母非元音
		if (cons[s[0]-'a'] == 0 || vowel[s[s.length-1]-'a'] == 0)
		    return false;
		    
		int i = 0;
		boolean a = false, b = false, c = false, d = false; 
		while (i < s.length && cons[s[i]-'a'] > 0) {
			a = true;
			i++;
		}
		while (i < s.length && vowel[s[i]-'a'] > 0) {
			b = true;
			i++;
		}
		while (i < s.length && cons[s[i]-'a'] > 0) {
			c = true;
			i++;
		}
		while (i < s.length && vowel[s[i]-'a'] > 0) {
			d = true;
			i++;
		}
		if (i == s.length && a && b && c && d)
		    return true;
	    return false;
    }
}
复杂度分析
  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( 1 ) O(1) O(1)

方法二:统计高度和的为 1 的个数

  • 元音 vowel 的高度设为 1,辅音 cons 的高度设为 0.
  • 最后统计两个字符之间的高度和为 1 的数量是否为 3 即可。
import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
    static int[] vowel, cons;
    public static void main(String[] args) throws IOException {  
        Scanner sc = new Scanner(new BufferedInputStream(System.in));
        PrintWriter pw = new PrintWriter(System.out, true); //自动刷新
		char[] s = sc.next().toCharArray();
	    if (check(s))
	        System.out.println("yes");
        else System.out.println("NO");
    }
    private static boolean check(char[] s) {
        if (s.length < 4)
		    return false;
		if (isVowel(s[0]) || !isVowel(s[s.length-1]))
		    return false;
	    int[] arr = new int[s.length];
	    for (int i = 0; i < s.length; i++) {
	        if (isVowel(s[i]))
	            arr[i] = 1;
            else 
                arr[i] = 0;
	    }
	    int cnt = 0;
	    for (int i = 1; i < arr.length; i++) {
	        if (arr[i] + arr[i-1] == 1)
	            cnt++;
	    }
	    return cnt == 3;
    }
    private static boolean isVowel(char c) {
        return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u';
    }
}

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( n ) O(n) O(n)

G(设) 递增三元组的中心

在数列 a [ 1 ] , a [ 2 ] , . . . , a [ n ] a[1], a[2], ..., a[n] a[1],a[2],...,a[n] 中,如果对于下标 i , j , k i, j, k i,j,k 满足 0 < i < j < k < n + 1 0<i<j<k<n+1 0<i<j<k<n+1 a [ i ] < a [ j ] < a [ k ] a[i]<a[j]<a[k] a[i]<a[j]<a[k],则称 a [ i ] , a [ j ] , a [ k ] a[i], a[j], a[k] a[i],a[j],a[k] 为一组递增三元组, a [ j ] a[j] a[j] 为递增三元组的中心。

给定一个数列,请问数列中有多少个元素可能是递增三元组的中心。

输入格式

  • 输入的第一行包含一个整数 n。
  • 第二行包含 n 个整数 a[1], a[2], …, a[n],相邻的整数间用空格分隔,表示给定的数列。

输出格式

  • 输出一行包含一个整数,表示答案。
样例输入
5
1 2 5 3 5
样例输出
2
样例说明
a[2] 和 a[4] 可能是三元组的中心。

评测用例规模与约定

  • 对于 50% 的评测用例,2 <= n <= 100,0 <= 数列中的数 <= 1000。
  • 对于所有评测用例,2 <= n <= 1000,0 <= 数列中的数 <= 10000。

方法一:暴力

n 最大为 1000,所以 O ( n 3 ) O(n^3) O(n3) 算法运行次数大概为 O ( 100 0 3 ) O(1000^3) O(10003),大概 1 0 9 10^9 109 即 10 亿次,肯定超时,所以只能得 50 % 50\% 50% 的分。

for(int i = 0; i < N-2; i++)
for(int j = i+1; j < N-1; j++)
for(int k = j+1; k < N; k++) {
	...
}
复杂度分析
  • 时间复杂度: O ( n 3 ) O(n^3) O(n3)
  • 空间复杂度: O ( 1 ) O(1) O(1)

方法二:优化

不必从某两个端点开始枚举。

  • 我们可以在区间 [0, p2] 内判断 p2 位置的数是否是该区间 [0, p2] 的最大的数。
    • 如果是,再从 p2 往后继续寻找一个比 arr[p2] 要大的数的下标。
    • 否则,枚举下一个区间 [0, p2+1]
import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
    public static void main(String[] args) throws IOException {  
        Scanner sc = new Scanner(new BufferedInputStream(System.in));
        PrintWriter pw = new PrintWriter(System.out, true); //自动刷新
        
		int N = sc.nextInt();
		int[] arr = new int[N];
		for (int i = 0; i < N; i++)  {
			arr[i] = sc.nextInt();
		}
		int count = 0;
		for (int i = 1; i < N; i++) {
			boolean up  = false;
			for (int j = 0; j < i; j++) {
				if (arr[j] < arr[i]) {
					up = true;
					break;
				}
			}
			if (up == false)
	            continue;
            boolean up2 = false;
		    for (int k = i + 1; k < N; k++) {
				if (arr[k] > arr[i]) {
				    up2 = true;
				    break;
				}
			}
			if (up && up2)
			    count++;
		}
		System.out.println(count);
    }
}
复杂度分析
  • 时间复杂度: O ( n 2 ) O(n^2) O(n2)
  • 空间复杂度: O ( 1 ) O(1) O(1)

H(设) 正整数序列的个数

小明想知道,满足以下条件的正整数序列的数量:

  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。

方法一:暴搜

题目说的是第 3 项小于第 1 和 第 2 项之差的绝对值,第 4 项小于第 2 和 第 3 项之差的绝对值,一次类推,一开始没看懂,hh。递推式为:

  • f ( a , b ) = f ( a , b − 1 ) + 1 f(a, b) = f(a, b-1) + 1 f(a,b)=f(a,b1)+1
  • f ( a , b − 1 ) = f ( b − 1 ,   1... b − 1 ) + 1 f(a, b-1) = f(b-1,\ 1...b-1) + 1 f(a,b1)=f(b1, 1...b1)+1

怎么用编程语言描述?总不能写 n 个相同的逻辑把,这里直接用递归。

import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
	private static int MOD = 10000;
	static long count;
    public static void main(String[] args) throws IOException {  
        Scanner sc = new Scanner(new BufferedInputStream(System.in));
        BufferedWriter w = new BufferedWriter(new OutputStreamWriter(System.out));
        
		int N = sc.nextInt();
		for (int i = 1; i <= N; i++) {
			dfs(N, i);
		}
		w.write(count + "");
		w.flush();;
    }
	private static void dfs(int a, int b) {
		if (Math.abs(a-b) < 0)
			return;
		count++;
		for (int i = 1; i < Math.abs(a-b); i++) {
			dfs(b, i);
		}
	}
}
复杂度分析
  • 时间复杂度: O ( ) O() O(),不怎么会算这种递归的复杂度
  • 空间复杂度: O ( ) O() O()

方法二:记忆化搜索

一般 dfs 的参数有几个,记忆数组就有几维。

* 不完美的 80%:

import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
	private static int MOD = 10000;
	static long count;
    public static void main(String[] args) throws IOException {  
        Scanner sc = new Scanner(new BufferedInputStream(System.in));
        BufferedWriter w = new BufferedWriter(new OutputStreamWriter(System.out));
        
		int N = sc.nextInt();
		memo = new long[N+1][N+1];
		long res = 0;
		for (int i = 1; i <= N; i++) {
			res += dfs(N, i);
		}
		w.write(res + "");
		w.flush();;
    }
	static long[][] memo;
	private static long dfs(int a, int b) {
		if (memo[a][b] != 0)
			return memo[a][b];
		long count = 1;
		for (int i = 1; i < Math.abs(a-b); i++) {
			count += dfs(b, i);
			count %= MOD;
		}
		return memo[a][b] = count;
	}
}

复杂度分析

  • 时间复杂度: O ( N 3 ) O(N^3) O(N3),N 到 600 的时候,就差不多需要 1s 了
  • 空间复杂度: O ( N 2 ) O(N^2) O(N2)

I(设) 杂草丛生

小明有一块空地,他将这块空地划分为 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。

方法一:枚举(非 bfs)

枚举 k 次,每一次将草 g 上下的 . 变为 g


复杂度分析
  • 时间复杂度: O ( ) O() O()
  • 空间复杂度: O ( ) O() O()

方法一:多源 bfs

首先将所有的草 g 入队,然后 bfs 即可


复杂度分析
  • 时间复杂度: O ( ) O() O()
  • 空间复杂度: O ( ) O() O()

J(设) 组织晚会

小明要组织一台晚会,总共准备了 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。

尝试一:二次排序(错误)

血亏:第一眼的思路就是这个,而且还去实现了,测试样例也输出正确,但是一分都得不了。假如有一组数据为:

10 7
15 56 59 41 69 66 6 76 15 50

按照这样的选法,选出来的数据就是:

56 59 41 69 66 76 50 

观察一下,会发现:第一个选 56 是错的,因为第一个节目应该选 59 才是满足观众的需求的,尽管好看度总和并不是最大,这题毕竟不是求好看度总和,观众认为前几个好看,整体就好看…

import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
    public static void main(String[] args) throws IOException {  
        Scanner sc = new Scanner(new BufferedInputStream(System.in));
        BufferedWriter w = new BufferedWriter(new OutputStreamWriter(System.out));
        
		int N = sc.nextInt();
		int m = sc.nextInt();
		int[] arr = new int[N];
		Map<Integer, Integer> map = new HashMap<>();
		for (int i = 0; i < N; i++) {
			arr[i] = sc.nextInt();
			map.put(arr[i], i);
		}
		List<Pair> list = new ArrayList<>();
		Arrays.sort(arr);
		for (int i = N-1; i >= N-m; i--) {
			int idx = map.get(arr[i]);
			list.add(new Pair(idx, arr[i]));
		}
		
		Collections.sort(list, (e1, e2)->e1.idx - e2.idx);
		for (Pair p : list) {
			w.write(p.n + " ");
		}
		w.flush();
    }
	static class Pair {
		int idx, n;
		public Pair(int _idx, int _n) {
			idx = _idx;
			n = _n;
		}
	}
}
复杂度分析
  • 时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)
  • 空间复杂度: O ( n ) O(n) O(n)

方法二:枚举

题目说:观众希望第一个节目尽可能好看”并希望“第二个节目尽可能好看,所以我们只能在 [0, n-m] 中选一个最好看的,然后从 [lastMaxIdx+1, n-m+1] 中选最大,更新最大值下标 lastMaxIdx

只能得 60% 分,数据最大为 100000,即 1 0 5 10^5 105 O ( 1 0 5 ) 2 O(10^5)^2 O(105)2 = O ( 1 0 10 ) O(10^{10}) O(1010),1s 时限是超时的, 1 0 5 10^5 105 的数据复杂度至少 O ( n l o g n ) O(nlogn) O(nlogn)

import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
    public static void main(String[] args) throws IOException {  
        Scanner sc = new Scanner(new BufferedInputStream(System.in));
        BufferedWriter w = new BufferedWriter(new OutputStreamWriter(System.out));
        
		int n = sc.nextInt();
		int m = sc.nextInt();
		int[] arr = new int[n];
		for (int i = 0; i < n; i++) {
			arr[i] = sc.nextInt();
		}
		int p1 = 0, p2 = n-m, pm = p1;

		while (p1 < p2) {
			while (p1 < p2) {
				if (arr[++p1] > arr[pm])
					pm = p1;
			}
			w.write(arr[pm] + " ");
			p1 = pm + 1;
			p2++;
			if (p2 >= n)
				break;
		}
		while (p2 < n) {		//指针重合证明
			w.write(arr[p2++] + " ");
		}
		w.flush();
    }
}

复杂度分析

  • 时间复杂度: O ( n 2 ) O(n^2) O(n2)
  • 空间复杂度: O ( 1 ) O(1) O(1)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值