【模拟赛】2019 蓝桥杯省赛 B 组模拟赛(一)
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
开始枚举所有的质数。- 如果找到两个质数
i
和j
,并且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
。- 既然你都想到这个地步了,互补关系啊,如果
i
和n-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]
时,l
和r
才各自移动1
,其他情况我们只让l
移动。 - 当
l <= r
,我们继续 while 循环,因为l==r
,N
为奇数时,中间还有一个人;而 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 组模拟赛(一)相关推荐
- 2018蓝桥杯省赛java_蓝桥杯2018年A组省赛
1.分数 1/1 + 1/2 + 1/4 + 1/8 + 1/16 + - 每项是前一项的一半,如果一共有20项, 求这个和是多少,结果用分数表示出来. 类似: 3/2 当然,这只是加了前2项而已.分 ...
- 2020年 第11届 蓝桥杯 C/C++ B组 省赛真题详解及小结【第1场省赛2020.7.5】【Java版】
蓝桥杯 Java B组 省赛真题详解及小结汇总[2013年(第4届)~2020年(第11届)] 注意:部分代码及程序 源自 蓝桥杯 官网视频(历年真题解析) 郑未老师. 2013年 第04届 蓝桥杯 ...
- 2015年第六届蓝桥杯C/C++B组省赛题目解析
1.奖券数目 有些人很迷信数字,比如带"4"的数字,认为和"死"谐音,就觉得不吉利. 虽然这些说法纯属无稽之谈,但有时还要迎合大众的需求.某抽奖活动的奖券号码是 ...
- 2019年第十届蓝桥杯C/C++ A组国赛赛后总结(北京旅游总结)
听说蓝桥杯挺水,几个同学一块儿报了省赛准备打着玩玩(Java C/C++ A B组都有).我报的是C/C++A组. 好,省赛一结束,一等奖前排...但是只有两个同C/C++A组的同学也是省一,不过都是 ...
- 蓝桥杯c语言a组省赛试题及答案,2016-蓝桥杯-省赛-C语言大学A组全部真题.doc
第七届蓝桥杯大赛个人赛省赛真题(软件类) C/C++ 大学A组 考生须知: 考试开始后,选手首先下载题目,并使用考场现场公布的解压密码解压试题. 考试时间为4小时.时间截止后,提交答案无效. 在考试强 ...
- 第九届蓝桥杯c/c++A组省赛题解
分数 题目 1/1 + 1/2 + 1/4 + 1/8 + 1/16 + - 每项是前一项的一半,如果一共有20项, 求这个和是多少,结果用分数表示出来. 类似:3 / 2 当然,这只是加了前2项而已 ...
- c语言苏小江第九章实验题答案,蓝桥杯C语言C组校内赛题目解析
今天事非常多,所有事情都凑在一起忙的不可开交.早上社团原本要搞活动,又恰好凑上实训课,三四节来不及搬东西过去,只能下课后再过去帮忙,手机没电,还是要忙到接近12点半才来得及回宿舍吃外卖. 饭还没吃几口 ...
- 2023第十四届蓝桥杯C/C++B组省赛题解
2023蓝桥C/C++B组省赛 文章目录 2023蓝桥C/C++B组省赛 试题A: 日期统计 题目描述 枚举 参考代码 试题B: 01 串的熵 题目描述 枚举|模拟 参考代码 试题C: 冶炼金属 题意 ...
- 2017年第八届蓝桥杯C/C++ B组省赛历年真题及解析
默认阅读的你具备c/c++基本语法,作者对每一题点明需要掌握的算法策略或思想,并进行简单注释解释: 该博客的正确食用方式:简单了解点明的算法思想和策略,再自行思索之后自己写代码,提交不过再看看别人的代 ...
- 2017第八届蓝桥杯C/C++ B组省赛题解
前言: 毕业前最后一次蹭一次公费旅游了.以前都是在成都,这次在绵阳,至少不用早起了.应该是最后一次玩蓝桥杯了. 尊重原创,转载请注明出处:http://blog.csdn.net/y119664537 ...
最新文章
- 我就不信看完这篇你还搞不懂信息熵
- Django基础核心技术之Model模型的介绍与设计
- structs2多文件上传
- android volley 上传图片 和参数,android Volley 上传文件上传图片
- JavaFX UI控件教程(十六)之Separator
- java.util.Date和java.sql.Date 一点区别
- 方德系统装exe文件_国产x86处理器+中科方德定制Linux 完美运行exe
- 关于Js(四)------ jquery ajax 中json接收数据注意事项
- in function ‘int main()’_FIND_IN_SET 及IN 处理逗号间隔的字符串参数
- 万豪国际数据再遭泄露影响520万客户,两名员工账户为突破口
- Visual C++ 2008入门经典 第二十一章更新数据源
- js 获取iframe页面元素
- Cocos2d-x特殊节点对象(瓦片地图、粒子系统、视差滚动)概述
- undefined reference to `create_module''
- allegro设置快捷键
- Why it occurs this error [The JSON value could not be converted to System.Nullable]
- 用计算机控制单片机的程序编写,单片机程序编写步骤
- 平安人寿“内鬼”泄露近4万条公民信息
- jQuery—常用API(jQuery 属性操作、jQuery 文本属性值、jQuery 元素操作)
- 第二部分 : 简单句的核心变化(时态)
热门文章
- Qt 和MFC对比及Qt跨平台优势
- LearningOpenCV详细入门操作
- Flask入门,看这一篇就够了
- pyinstall 打包
- php二维数组实例_什么是php二维数组?php二维数组实例详解
- 一文详尽固定收益证券
- Java MVC+structs2+mysql实现的宿舍管理系统(功能:楼宇管理员管理、学生管理、楼宇管理、宿舍管理、学生入住登记、学生寝室调换、学生迁出登记、学生缺勤记录、迁出记录、修改密码)
- 【QQ红包】手机发抢不到的口令红包
- 随机点名系统----数据库
- Anaconda+Tensorflow_Gpu+Spyder安装记录(2022年10月14日更新)