A(填) 钟表

方法一:利用 23:59:60


B(填) 青蛙爬井

方法一:枚举

* 危,严重错误:算出来是 862,感觉心都凉了。day 竟然是从 1 开始的。

import java.util.*;
import java.math.*;
public class Main {public static void main(String[] args) {int h = 60405, up = 105, down = 35;int day = 0;  //1int cur = 0;while (true) {cur += up;if (cur >= h)break;cur -= down;day++;}System.out.println(day);}
}

答案:863


C(填) 倍数

* 数据问题:12302135942453 这个数用 long 类型是装不下的,不知道为什么 c++ 可以用 long long,这题用 Java 只能用 BigInteger。

方法一:BigInteger

import java.util.*;
import java.math.*;
public class Main{public static void main(String[] args) {  long r = 12302135942453;int count = 0;for (long l = 1032; l <= r; l++) {if (l % 234 == 0)count++;}System.out.println(count);}
}

* 效率出错:知道你想从 1032 枚举到 12302135942453,数值真的太大了,想一下,这题只是要算倍数的个数。不妨把 r 选 8 试试看,算一下 [3,8] 中 2 的倍数的个数。

4, 6, 8

8 2 = 4 \cfrac{8}{2} = 4 28​=4,但有 1 个数被下界忽略了,所以要减 1。不过使用 BigInteger 算一下就当熟悉一下 API 了,用到的 api 挺多的,乘,除,取模,比较…

import java.util.*;
import java.math.*;
public class Main{public static void main(String[] args) {  BigInteger r = new BigInteger("12302135942453"); //注:数值太大,只能用 创建对象的方式BigInteger l = BigInteger.valueOf(1032);BigInteger d = BigInteger.valueOf(234);System.out.println(r.divide(d).subtract(l.divide(d)));}
}

答案:52573230519


D(填) 马的管辖

方法一:


答案:

复杂度分析

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

E(填) LIS


F(设) 找质数

方法一:枚举 + 素数打表(超时)

  • 先把 [2, MAXN] 区间中所有的素数计算出来。
  • 然后双重循环从 2 开始枚举所有的质数。
    • 如果找到两个质数 ij,并且 i + j = n,就 break 掉本次搜索,继续下一个数字的搜索。

* 超时错误:时间限制 1 s 1s 1s, 1 s 1s 1s 大概运行 3 k w 3kw 3kw(约 3 × 1 0 7 3 × 10^7 3×107) 次,该算法的复杂度最差为 O ( n 2 ) O(n^2) O(n2)。

  • 如果数据是 1 0 3 10^3 103,最差大概运行 ( 1 0 3 ) 2 (10^3)^2 (103)2 次,即 1 0 6 10^6 106,可以算法可以通过该范围的数据量。
  • 1 0 5 , 1 0 6 10^5,10^6 105,106 这些数据肯定不行。
  • 所以该算法只能拿 30 % 30\% 30% 的分数。
import java.util.*;
import java.math.*;
public class Main{static int MAXN = 1000050;public static void main(String[] args) {  Scanner sc = new Scanner(System.in);int N = sc.nextInt();int[] arr = new int[N];for (int i = 0; i < N; i++) {arr[i] = sc.nextInt();}boolean[] isPrime = getPrimes();for (int n : arr) {a:for (int i = 2; i < n; i++) {if (isPrime[i] == false)continue;for (int j = 2; j < n; j++)      //可优化if (isPrime[j] && i + j == n)  {System.out.println(i + " " + j);break a;}}}}//素数打表private static boolean[] getPrimes() {boolean[] isPrime = new boolean[MAXN];Arrays.fill(isPrime, true);for (int i = 2; i <= Math.sqrt(MAXN); i++) {if (isPrime[i]) {for (int j = i+i; j < MAXN; j+=i) isPrime[j] = false;}}return isPrime;}
}

* 优化方案:

  • 优化一:当 isPrime[i] == false 时,我们 continue 即可,不用继续枚举 j
  • 优化二:当 i 是质数时,j 只用枚举到 n-i
    • 既然你都想到这个地步了,互补关系啊,如果 in-i 都是素数,那么输出即可,所以我们可以将二重循环优化为单重循环。

方法二:利用互补关系

* 超时错误:为什么优化为 O(n) 却只能过掉 50% 的数据,我们来分析一下:

  • 中间的 O ( n ) O(n) O(n) 逻辑肯定没有问题的,问题可能在素数打表那里。
  • 要么是 Java 的输入太慢了。
import java.util.*;
import java.math.*;
public class Main{static int MAXN = 1000005;public static void main(String[] args) {  Scanner sc = new Scanner(System.in);int N = sc.nextInt();int[] arr = new int[N];for (int i = 0; i < N; i++) {arr[i] = sc.nextInt();}boolean[] notPrime = new boolean[MAXN];// Arrays.fill(notPrime, true);    取反逻辑可以减少该步骤for (int i = 2; i * i <= MAXN; i++) {if (notPrime[i] == false) {for (int j = i*i; j < MAXN; j+=i) notPrime[j] = true;}}for (int n : arr)for (int i = 2; ;i++) {if (!notPrime[i] && !notPrime[n-i]) {System.out.println(i + " " + (n-i));break;}}}
}

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n),
  • 空间复杂度: O ( M A X N ) O(MAXN) O(MAXN),

G(设) 后缀字符串

一天蒜头君得到 n 个字符串 si​,每个字符串的长度都不超过 10。蒜头君在想,在这 n 个字符串中,以 si​ 为后缀的字符串有多少个呢?

输入格式

  • 第一行输入一个整数 n。
  • 接下来 n 行,每行输入一个字符串 si​。

输出格式

  • 输出 n 个整数,第 i 个整数表示以 si​ 为后缀的字符串的个数。

数据范围

  • 对于 50% 的数据, 1 ≤ n ≤ 1 0 3 1≤n≤10^3 1≤n≤103。
  • 对于 100% 的数据, 1 ≤ n ≤ 1 0 5 1≤n≤10^5 1≤n≤105。

所有的字符串仅由小写字母组成。

样例输入

3
ba
a
aba

样例输出

2
3
1

尝试一:暴力枚举(超时)

import java.util.*;
import java.math.*;
public class Main{public static void main(String[] args) {  Scanner sc = new Scanner(System.in);int n = sc.nextInt();String[] ss = new String[n];for (int i = 0; i < n; i++) {ss[i] = sc.next();}int[] res = new int[n];for (int i = 0; i < n; i++)for (int j = 0; j < n; j++) {if (ss[i].length() > ss[j].length())continue;if (ss[j].lastIndexOf(ss[i]) != -1)res[i]++;}for (int i : res)    System.out.println(i);}
}

* 超时错误:暴力枚举的复杂度是 O ( n 2 × 10 ) O(n^{2 × 10}) O(n2×10),而 1 秒大概可以做 3 k w 3kw 3kw 次循环,所以对于后 % 50 \%50 %50 的数据,无法通过。但真的是超时错误码? 为什么一组样例都过不了…

* API 使用错误:lastIndexOf:从后往前遍历查找对应字符串,返回查找字符串首个字符位置(从0开始查找),未找到返回 -1;考试这样做,凉凉咯…

  • 注:查找方向是从右往左

方法一:匹配前缀

还是先反转一下所有字符串,然后匹配前缀把。

import java.util.*;
import java.math.*;
public class Main{public static void main(String[] args) {  Scanner sc = new Scanner(System.in);int n = sc.nextInt();String[] ss = new String[n];for (int i = 0; i < n; i++) {ss[i] = reverse(sc.next());}    for (int i = 0; i < n; i++) {int res = 0;for (int j = 0; j < n; j++) {if (ss[j].indexOf(ss[i]) == 0)res++;     }System.out.println(res);}}private static String reverse(String str) {char[] s = str.toCharArray();int l = 0, r = s.length-1;while (l < r) {char c = s[l];s[l++] = s[r];s[r--] = c;}return new String(s);}
}

复杂度分析

  • 时间复杂度: O ( n 2 ) O(n^2) O(n2),
  • 空间复杂度: O ( 1 ) O(1) O(1),

方法二:map

不如,我们直接把 ss[i] 的每一个子串用 map 记录一下出现次数,比如对于 ss = ["aba", "ba"],我们可以这样统计子字符串的个数:

map["aba"]= 1
map["ba"] = 1
map["a"]  = 1
map["ba"] = 2
map["a"] = 2

下次找后缀子串 "ba" 时,很明显 ss 中有两个串是以 "ba" 结尾的。

import java.util.*;
import java.math.*;
public class Main{public static void main(String[] args) {  Scanner sc = new Scanner(System.in);int n = sc.nextInt();Map<String, Integer> map = new HashMap<>();String[] ss = new String[n];for (int i = 0; i < n; i++) {ss[i] = sc.next();for (int j = 0; j < ss[i].length(); j++) {String sub = ss[i].substring(j);map.put(sub, map.getOrDefault(sub, 0) + 1);}}for (String s : ss) {System.out.println(map.get(s));}}
}

复杂度分析

  • 时间复杂度: O ( 10 × n ) O(10 × n) O(10×n),字符串长度最长不超过 10。
  • 空间复杂度: O ( n ) O(n) O(n),

H(设) 轻重搭配

n 个同学去动物园参观,原本每人都需要买一张门票,但售票处推出了一个优惠活动,一个体重为 x 的人可以和体重至少为 2x 配对,这样两人只需买一张票。现在给出了 n 个人的体重,请你计算他们最少需要买几张门票?

输入格式

  • 第一行一个整数 n,表示人数。
  • 第二行 n 个整数,每个整数 a i a_i ai​ 表示每个人的体重。

输出格式

  • 一个整数,表示最少需要购买的门票数目。

尝试一:排序 + 双指针?

* 得分失误:这样写一份都得不到!为什么,因为该算法是片面的。

似乎这个偶数个的数组 arr = [1 3 5 5 7 9] 样例可以过,但你有没有注意到如果 N 是奇数的时候,你的程序输出什么?比如 arr = [1 3 5 5 6 7 9] 时,按理说应该需要 5 张票,如果按照下面的算法,则输出了 4唉…粗心了。

import java.util.*;
import java.math.*;
public class Main{public static void main(String[] args) {  Scanner sc = new Scanner(System.in);int N = sc.nextInt();int[] arr = new int[N];for (int i = 0; i < N; i++)arr[i] = sc.nextInt();int count = 0;Arrays.sort(arr);int l = 0, r = N-1;while (l < r) {if (2 * arr[l] <= arr[r]) {count++;} else {count += 2;}l++; r--;}System.out.println(count);}
}

* 更正逻辑:

  • 2 * arr[l] <= arr[r]时,lr 才各自移动 1,其他情况我们只让 l 移动。
  • l <= r,我们继续 while 循环,因为 l==rN 为奇数时,中间还有一个人;而 N 为偶数时,程序依然正确。

* 混分:这样写可以拿 1 分,但总比没有强。

* 错误原因:贪心策略错了,最重的和最轻的搭配无疑造成了浪费。

import java.util.*;
import java.math.*;
public class Main{public static void main(String[] args) {  Scanner sc = new Scanner(System.in);int N = sc.nextInt();int[] arr = new int[N];for (int i = 0; i < N; i++)arr[i] = sc.nextInt();int count = 0;Arrays.sort(arr);int l = 0, r = N-1;while (l <= r) {if (2 * arr[l] <= arr[r]) {r--;l++; } else {l++;}count++;}System.out.println(count);}
}

尝试二:贪心

* 更正逻辑:我们知道任何一组数据最多能搭配的数量一定不超过 N 2 \cfrac{N}{2} 2N​ 对,其实我们可以这样做:

  • 把数组的后半部分 [ [ [ N 2 \cfrac{N}{2} 2N​, N ) N) N) 存到 set 中。
  • 然后枚举区间 [ 0 , [0, [0, N 2 \cfrac{N}{2} 2N​)里的数,从 set 中寻找第一个大于等于 2 * arr[i] 的数。
    • TreeSet 中有一个 ceiling(e) 方法可以找出大于等于 e 的最小元素。

* 超时错误:这样的算法用 java 实现只能过 % 30 \%30 %30 的数据。

import java.util.*;
import java.math.*;
public class Main{public static void main(String[] args) {  Scanner sc = new Scanner(System.in);int N = sc.nextInt();int[] arr = new int[N];for (int i = 0; i < N; i++)arr[i] = sc.nextInt();int count = N;Arrays.sort(arr);TreeSet<Integer> set = new TreeSet<>();int half = N/2;for (int i = half; i < N; i++) {set.add(arr[i]);}for (int i = 0; i < half; i++) {Integer other = set.ceiling(2*arr[i]);if (other == null)break;count--;set.remove(other);}System.out.println(count);}
}

复杂度分析

  • 时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn),
  • 空间复杂度: O ( n ) O(n) O(n),

方法二:贪心 + 双指针

既然数组已经有序,不适用 TreeSet 也可以在区间 [ N 2 , N ) \cfrac{N}{2},N) 2N​,N) 找到第一个大于 2*arr[l] 的元素。

* 正确逻辑:

  • count 初值为 N 代表不组队需要的票数,
  • 当可以组队时,我们让 count-- 表示比本来需要的票数少 1。
import java.util.*;
import java.math.*;
public class Main{public static void main(String[] args) {  Scanner sc = new Scanner(System.in);int N = sc.nextInt();int[] arr = new int[N];for (int i = 0; i < N; i++)arr[i] = sc.nextInt();int count = N;Arrays.sort(arr);int l = 0, r = N/2;while (l < N/2 && r < N) {if (2*arr[l] <= arr[r]) {l++; r++;count--;} else {r++;}}System.out.println(count);}
}

复杂度分析

  • 时间复杂度: O ( N l o g N ) O(NlogN) O(NlogN),
  • 空间复杂度: O ( 1 ) O(1) O(1),

I(设) 抠图


J(设) 蒜厂年会

在蒜厂年会上有一个抽奖,在一个环形的桌子上,有 n 个纸团,每个纸团上写一个数字,表示你可以获得多少蒜币。但是这个游戏比较坑,里面竟然有负数,表示你要支付多少蒜币。因为这些数字都是可见的,所以大家都是不会出现的赔的情况。

游戏规则:每人只能抓一次,只能抓取一段连续的纸团,所有纸团上的数字和就是你可以获得的蒜币。

蒜头君作为蒜厂的一员在想,我怎么可以获得最多的蒜币呢?最多能获取多少蒜币呢?

因为年会是发奖,那么一定有大于 0 的纸团。

输入格式

  • 第一行输入一个整数 n,表示有 n 个纸团。
  • 第二行输入输入 n 个整数 ai​,表示每个纸团上面写的数字(这些纸团的输入顺序就是环形桌上纸团的摆放顺序)。

输出格式

  • 输出一个整数,表示蒜头君最多能获取多少蒜币。

方法一:暴力(拆环)

这是一个环形问题,可用的做法是在末尾新增一段将环拆掉,然后暴力枚举每一子段的和,取其中的最大值。

超时错误: O ( n 3 ) O(n^3) O(n3) 的复杂度只能过掉 20 % 20\% 20% 的数据。

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[2*N+5];for (int i = 0; i < N; i++) {arr[i] = sc.nextInt();arr[i+N] = arr[i];}int max = 0;for (int i = 0; i < 2*N; i++)for (int j = 0; j < 2*N; j++) {int sum = 0;for (int k = i; k < j; k++) {sum += arr[k];}max = Math.max(max, sum);}System.out.println(max);}
}

复杂度分析

  • 时间复杂度: O ( N 3 ) O(N^3) O(N3),
  • 空间复杂度: O ( 1 ) O(1) O(1),

方法二:优化暴力(拆环)

其实我们可以在第 2 层循环就去求解字段和,每次加上一个元素就去判断是否大于 max,这样就省去了显式地求解一段区间的时间。

* 超时: O ( n 2 ) O(n^2) O(n2) 算法顶多承受 1 0 3 10^3 103 的数据量。


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[2*N+5];for (int i = 0; i < N; i++) {arr[i] = sc.nextInt();arr[i+N] = arr[i];}int max = 0;for (int i = 0; i < 2*N; i++) {int sum = 0;for (int j = i; j < 2*N; j++) {sum += arr[j];if (sum > max)max = sum;}}System.out.println(max);}
}

复杂度分析

  • 时间复杂度: O ( N 2 ) O(N^2) O(N2),
  • 空间复杂度: O ( 1 ) O(1) O(1),

方法三:dp

不是 O ( n ) O(n) O(n) 了吗?为什么只能得到一个 50 % 50\% 50% 的 WA.

* 未知错误:

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[2*N+5];for (int i = 0; i < N; i++) {arr[i] = sc.nextInt();arr[i+N] = arr[i];}int[] dp = new int[2*N];dp[0] = arr[0] < 0 ? 0 : arr[0];int max = 0;for (int i = 1; i < 2*N; i++) {dp[i] = Math.max(dp[i-1]+arr[i], dp[i]);max = Math.max(dp[i], max);}System.out.println(max);}
}

复杂度分析

  • 时间复杂度: O ( N ) O(N) O(N),
  • 空间复杂度: O ( 1 ) O(1) O(1),

【模拟赛】2019 蓝桥杯省赛 B 组模拟赛(一)相关推荐

  1. 2018蓝桥杯省赛java_蓝桥杯2018年A组省赛

    1.分数 1/1 + 1/2 + 1/4 + 1/8 + 1/16 + - 每项是前一项的一半,如果一共有20项, 求这个和是多少,结果用分数表示出来. 类似: 3/2 当然,这只是加了前2项而已.分 ...

  2. 2020年 第11届 蓝桥杯 C/C++ B组 省赛真题详解及小结【第1场省赛2020.7.5】【Java版】

    蓝桥杯 Java B组 省赛真题详解及小结汇总[2013年(第4届)~2020年(第11届)] 注意:部分代码及程序 源自 蓝桥杯 官网视频(历年真题解析) 郑未老师. 2013年 第04届 蓝桥杯 ...

  3. 2015年第六届蓝桥杯C/C++B组省赛题目解析

    1.奖券数目 有些人很迷信数字,比如带"4"的数字,认为和"死"谐音,就觉得不吉利. 虽然这些说法纯属无稽之谈,但有时还要迎合大众的需求.某抽奖活动的奖券号码是 ...

  4. 2019年第十届蓝桥杯C/C++ A组国赛赛后总结(北京旅游总结)

    听说蓝桥杯挺水,几个同学一块儿报了省赛准备打着玩玩(Java C/C++ A B组都有).我报的是C/C++A组. 好,省赛一结束,一等奖前排...但是只有两个同C/C++A组的同学也是省一,不过都是 ...

  5. 蓝桥杯c语言a组省赛试题及答案,2016-蓝桥杯-省赛-C语言大学A组全部真题.doc

    第七届蓝桥杯大赛个人赛省赛真题(软件类) C/C++ 大学A组 考生须知: 考试开始后,选手首先下载题目,并使用考场现场公布的解压密码解压试题. 考试时间为4小时.时间截止后,提交答案无效. 在考试强 ...

  6. 第九届蓝桥杯c/c++A组省赛题解

    分数 题目 1/1 + 1/2 + 1/4 + 1/8 + 1/16 + - 每项是前一项的一半,如果一共有20项, 求这个和是多少,结果用分数表示出来. 类似:3 / 2 当然,这只是加了前2项而已 ...

  7. c语言苏小江第九章实验题答案,蓝桥杯C语言C组校内赛题目解析

    今天事非常多,所有事情都凑在一起忙的不可开交.早上社团原本要搞活动,又恰好凑上实训课,三四节来不及搬东西过去,只能下课后再过去帮忙,手机没电,还是要忙到接近12点半才来得及回宿舍吃外卖. 饭还没吃几口 ...

  8. 2023第十四届蓝桥杯C/C++B组省赛题解

    2023蓝桥C/C++B组省赛 文章目录 2023蓝桥C/C++B组省赛 试题A: 日期统计 题目描述 枚举 参考代码 试题B: 01 串的熵 题目描述 枚举|模拟 参考代码 试题C: 冶炼金属 题意 ...

  9. 2017年第八届蓝桥杯C/C++ B组省赛历年真题及解析

    默认阅读的你具备c/c++基本语法,作者对每一题点明需要掌握的算法策略或思想,并进行简单注释解释: 该博客的正确食用方式:简单了解点明的算法思想和策略,再自行思索之后自己写代码,提交不过再看看别人的代 ...

  10. 2017第八届蓝桥杯C/C++ B组省赛题解

    前言: 毕业前最后一次蹭一次公费旅游了.以前都是在成都,这次在绵阳,至少不用早起了.应该是最后一次玩蓝桥杯了. 尊重原创,转载请注明出处:http://blog.csdn.net/y119664537 ...

最新文章

  1. 我就不信看完这篇你还搞不懂信息熵
  2. Django基础核心技术之Model模型的介绍与设计
  3. structs2多文件上传
  4. android volley 上传图片 和参数,android Volley 上传文件上传图片
  5. JavaFX UI控件教程(十六)之Separator
  6. java.util.Date和java.sql.Date 一点区别
  7. 方德系统装exe文件_国产x86处理器+中科方德定制Linux 完美运行exe
  8. 关于Js(四)------ jquery ajax 中json接收数据注意事项
  9. in function ‘int main()’_FIND_IN_SET 及IN 处理逗号间隔的字符串参数
  10. 万豪国际数据再遭泄露影响520万客户,两名员工账户为突破口
  11. Visual C++ 2008入门经典 第二十一章更新数据源
  12. js 获取iframe页面元素
  13. Cocos2d-x特殊节点对象(瓦片地图、粒子系统、视差滚动)概述
  14. undefined reference to `create_module''
  15. allegro设置快捷键
  16. Why it occurs this error [The JSON value could not be converted to System.Nullable]
  17. 用计算机控制单片机的程序编写,单片机程序编写步骤
  18. 平安人寿“内鬼”泄露近4万条公民信息
  19. jQuery—常用API(jQuery 属性操作、jQuery 文本属性值、jQuery 元素操作)
  20. 第二部分 : 简单句的核心变化(时态)

热门文章

  1. Qt 和MFC对比及Qt跨平台优势
  2. LearningOpenCV详细入门操作
  3. Flask入门,看这一篇就够了
  4. pyinstall 打包
  5. php二维数组实例_什么是php二维数组?php二维数组实例详解
  6. 一文详尽固定收益证券
  7. Java MVC+structs2+mysql实现的宿舍管理系统(功能:楼宇管理员管理、学生管理、楼宇管理、宿舍管理、学生入住登记、学生寝室调换、学生迁出登记、学生缺勤记录、迁出记录、修改密码)
  8. 【QQ红包】手机发抢不到的口令红包
  9. 随机点名系统----数据库
  10. Anaconda+Tensorflow_Gpu+Spyder安装记录(2022年10月14日更新)