蓝桥杯 2022年省赛真题
C/C++ 大学B组

  • 试题 A: 九进制转十进制
  • 试题 B: 顺子日期
  • 试题 C: 刷题统计
  • 试题 D: 修剪灌木
  • 试题 E: X 进制减法
  • 试题 F: 统计子矩阵
  • 试题 G: 积木画
  • 试题 H: 扫雷
  • 试题  I: 李白打酒加强版
  • 试题 J: 砍竹子

  省流,十道签到题。


试题 A: 九进制转十进制

本题总分:555 分


【问题描述】

  九进制正整数 (2022)9(2022)_9(2022)9​ 转换成十进制等于多少?

【答案提交】

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


1478


#include <stdio.h>int main() {int c, ans = 0;while (c = getchar(), '0' <= c && c <= '9')ans = ans * 9 + c - '0';printf("%d", ans);
}

  凭什么都是双非,C\mathrm CC 的签到难度这么低。

  不公平不公平,重赛!重赛!


试题 B: 顺子日期

本题总分:555 分


【问题描述】

  小明特别喜欢顺子。顺子指的就是连续的三个数字:123、456:123、456:123、456 等。顺子日期指的就是在日期的 yyyymmdd\mathrm{yyyymmdd}yyyymmdd 表示法中,存在任意连续的三位数是一个顺子的日期。例如 202201232022012320220123 就是一个顺子日期,因为它出现了一个顺子:123123123;而 202210232022102320221023 则不是一个顺子日期,它一个顺子也没有。小明想知道在整个 202220222022 年份中,一共有多少个顺子日期。


【答案提交】

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


14


#include <stdio.h>int year = 20220000, date, ans;int days[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, buff[8];int main() {for (int month = 1; month <= 12; ++month)for (int day = 1; day <= days[month]; ++day) {date = year + 100 * month + day;for (int i = 0; i < 8; ++i)buff[i] = date % 10, date /= 10;for (int i = 1; i < 7; ++i)if (buff[i] - buff[i + 1] == 1 &&buff[i - 1] - buff[i] == 1) {++ans;break;}}printf("%d", ans);
}

  虽然从题目描述中,无法直观的感受到所谓的顺子,是否包括如 321321321 这样递减的连续自然数列,但描述给出的样例 202210232022102320221023 中包含了 210210210,基本上可以认为答案中不包含递减的连续自然数列的统计,但同时还有另一个问题,那就是顺子中能否包含 000。

  总之,我认为是能包含 000 的,不愧是蓝桥,

  题面做的真是有够失败的呢。


试题 C: 刷题统计

时间限制: 1.0s1.0\mathrm s1.0s 内存限制: 256.0MB256.0\mathrm{MB}256.0MB 本题总分:101010 分


【问题描述】

  小明决定从下周一开始努力刷题准备蓝桥杯竞赛。他计划周一至周五每天做 aaa 道题目,周六和周日每天做 bbb 道题目。请你帮小明计算,按照计划他将在第几天实现做题数大于等于 nnn 题?

【输入格式】

  输入一行包含三个整数 a,ba, ba,b 和 nnn。

【输出格式】

  输出一个整数代表天数。

【样例输入】

10 20 99

【样例输出】

8

【评测用例规模与约定】

  对于 50%50\%50% 的评测用例,1≤a,b,n≤1061 ≤ a, b, n ≤ 10^61≤a,b,n≤106。
  对于 100%100\%100% 的评测用例,1≤a,b,n≤10181 ≤ a, b, n ≤ 10^{18}1≤a,b,n≤1018。


#include <stdio.h>long long a, b, n, ans;int main() {scanf("%lld %lld %lld", &a, &b, &n);ans = n / (5 * a + 2 * b) * 7;n %= 5 * a + 2 * b;if (n > 5 * a)ans += 5 + ((n - 5 * a) + b - 1) / b;elseans += (n + a - 1) / a;printf("%lld", ans);
}

  没啥好说的,

  一个 a/ba\ /\ ba / b 向上取整的小技巧就是 (a+b−1)/b(a + b - 1)\ /\ b(a+b−1) / b 向下取整。


试题 D: 修剪灌木

时间限制: 1.0s1.0\mathrm s1.0s 内存限制: 256.0MB256.0\mathrm{MB}256.0MB 本题总分:101010 分


【问题描述】

  爱丽丝要完成一项修剪灌木的工作。

  有 NNN 棵灌木整齐的从左到右排成一排。爱丽丝在每天傍晚会修剪一棵灌木,让灌木的高度变为 000 厘米。爱丽丝修剪灌木的顺序是从最左侧的灌木开始,每天向右修剪一棵灌木。当修剪了最右侧的灌木后,她会调转方向,下一天开始向左修剪灌木。直到修剪了最左的灌木后再次调转方向。然后如此循环往复。

  灌木每天从早上到傍晚会长高 1 厘米,而其余时间不会长高。在第一天的早晨,所有灌木的高度都是 000 厘米。爱丽丝想知道每棵灌木最高长到多高。

【输入格式】

  一个正整数 NNN ,含义如题面所述。

【输出格式】

  输出 NNN 行,每行一个整数,第行表示从左到右第 iii 棵树最高能长到多高。

【样例输入】

3

【样例输出】

4
2
4

【评测用例规模与约定】

  对于 30%30\%30% 的数据,N≤10N ≤ 10N≤10。
  对于 100%100\%100% 的数据,1<N≤100001 < N ≤ 100001<N≤10000。


#include <stdio.h>int n;int max(int a, int b) { return a > b ? a : b; }int main() {scanf("%d", &n);if (n == 1) putchar('1');else for (int i = 1; i <= n; ++i)printf("%d\n", 2 * max(i - 1, n - i));
}

  一颗灌木可以长到的最高高度,可能为:

  1. 在它第一次被修剪之前
  2. 它在某一次被修剪后,在此被修剪之前。

  对于第二种情况,很容易分类出第 iii 个灌木 tit_iti​ 的最高高度为 max⁡{2×(i−1),2×(n−i)}\max\{2 × (i - 1),2 × (n-i)\}max{2×(i−1),2×(n−i)},即对应着爱丽丝从左端点折返和爱丽丝从右端点折返 tit_iti​ 能达到的最高高度的取值。

  同时 2×(i−1)≤i2 × (i - 1) \leq i2×(i−1)≤i,仅在 i≤1i \leq 1i≤1 成立,故对于第一种情况,无需额外的判断,直接取第二种情况的最大值即可。


试题 E: X 进制减法

时间限制: 1.0s1.0\mathrm s1.0s 内存限制: 256.0MB256.0\mathrm{MB}256.0MB 本题总分:151515 分


【问题描述】

  进制规定了数字在数位上逢几进一。

  XXX 进制是一种很神奇的进制,因为其每一数位的进制并不固定!例如说某种 XXX 进制数,最低数位为二进制,第二数位为十进制,第三数位为八进制,则 XXX 进制数 321321321 转换为十进制数为 656565。

  现在有两个 XXX 进制表示的整数 AAA 和 BBB,但是其具体每一数位的进制还不确定,只知道 AAA 和 BBB 是同一进制规则,且每一数位最高为 NNN 进制,最低为二进制。请你算出 A−BA − BA−B 的结果最小可能是多少。

  请注意,你需要保证 AAA 和 BBB 在 XXX 进制下都是合法的,即每一数位上的数字要小于其进制。

【输入格式】

  第一行一个正整数 NNN,含义如题面所述。

  第二行一个正整数 MaM_aMa​,表示 XXX 进制数 AAA 的位数。

  第三行 MaM_aMa​ 个用空格分开的整数,表示 XXX 进制数 AAA 按从高位到低位顺序各个数位上的数字在十进制下的表示。

  第四行一个正整数 MbM_bMb​,表示 XXX 进制数 BBB 的位数。

  第五行 MbM_bMb​ 个用空格分开的整数,表示 XXX 进制数 BBB 按从高位到低位顺序各个数位上的数字在十进制下的表示。

  请注意,输入中的所有数字都是十进制的。

【输出格式】

  输出一行一个整数,表示 XXX 进制数 A−BA − BA−B 的结果的最小可能值转换为十进制后再模 100000000710000000071000000007 的结果。

【样例输入】

11
3
10 4 0
3
1 2 0

【样例输出】

94

【样例说明】
  当进制为:最低位 222 进制,第二数位 555 进制,第三数位 111111 进制时,减法得到的差最小。此时 AAA 在十进制下是 108108108,BBB 在十进制下是 141414,差值是 949494。

【评测用例规模与约定】

  对于 30%30\%30% 的数据,N≤10;Ma,Mb≤8N ≤ 10; M_a, M_b ≤ 8N≤10;Ma​,Mb​≤8。
  对于 100%100\%100% 的数据,2≤N≤1000;1≤Ma,Mb≤100000;A≥B2 ≤ N ≤ 1000; 1 ≤ M_a, M_b ≤ 100000; A ≥ B2≤N≤1000;1≤Ma​,Mb​≤100000;A≥B。


#include <stdio.h>typedef long long ll;int n, m, ma, mb, ans, p = 1000000007;int A[100010], B[100010], S[100010] = {1};int max(int a, int b) { return a > b ? a : b; }int main() {scanf("%d", &n);scanf("%d", &ma);for (int i = ma; i > 0; --i) scanf("%d", &A[i]);scanf("%d", &mb);for (int i = mb; i > 0; --i) scanf("%d", &B[i]);for (int i = 1; i <= max(ma, mb); ++i) {S[i] = (ll)(max(1, max(A[i], B[i])) + 1) * S[i - 1] % p;ans = (ans + (ll)S[i - 1] * (A[i] - B[i]) % p + p) % p;}printf("%d", ans);
}

  稍微转变一下就是,设 m=max⁡{ma,mb}m = \max\{m_a,m_b\}m=max{ma​,mb​},找到一个序列 S={si∣si≤N∣si>Ai,Bi,1}S = \{s_i | s_i \leq N|s_i>A_i,B_i,1\}S={si​∣si​≤N∣si​>Ai​,Bi​,1},s0=1s_0 = 1s0​=1,∣S∣=m|S| = m∣S∣=m,使得 ∑i=1m[∏j=0i−1sj(Ai−Bi)]\sum_{i=1}^m[\prod_{j=0}^{i-1}s_j(A_i - B_i)]∑i=1m​[∏j=0i−1​sj​(Ai​−Bi​)] 最小,

  对于任意合法 nnn、XXX,∏i=0nsi>∑i=1n−1(xi∏j=0i−1sj)\prod_{i=0}^{n}s_i > \sum_{i=1}^{n-1}(x_i\prod_{j=0}^{i-1}s_j)∏i=0n​si​>∑i=1n−1​(xi​∏j=0i−1​sj​) 都成立,因为 ∏i=0nsi=1+∑i=1n−1[(si−1)∏j=0i−1sj]\prod_{i=0}^{n}s_i = 1 + \sum_{i=1}^{n-1}[(s_i - 1)\prod_{j=0}^{i-1}s_j]∏i=0n​si​=1+∑i=1n−1​[(si​−1)∏j=0i−1​sj​]。

  因为 A≥BA \geq BA≥B,所以必然存在一个最小的 iii,使得所有 i′>ii' > ii′>i 都有 Ai′=Bi′A_{i'} = B_{i'}Ai′​=Bi′​ 且 Ai≥BiA_i \geq B_iAi​≥Bi​,我们的任务就是构造 SSS 使得 (Ai−Bi)∏j=0i−1sj(A_i - B_i)\prod_{j=0}^{i-1}s_j(Ai​−Bi​)∏j=0i−1​sj​ 最小。

  因此每个 sis_isi​ 取最小值即可。


试题 F: 统计子矩阵

时间限制: 1.0s1.0\mathrm s1.0s 内存限制: 256.0MB256.0\mathrm{MB}256.0MB 本题总分:151515 分


【问题描述】

  给定一个 N×MN × MN×M 的矩阵 AAA,请你统计有多少个子矩阵 (最小 1×11 × 11×1,最大 N×MN × MN×M) 满足子矩阵中所有数的和不超过给定的整数 K?K?K?

【输入格式】

  第一行包含三个整数 N,MN, MN,M 和 KKK。

  之后 NNN 行每行包含 MMM 个整数,代表矩阵 AAA。

【输出格式】

  一个整数代表答案。

【样例输入】

3 4 10
1 2 3 4
5 6 7 8
9 10 11 12

【样例输出】

19

【样例说明】
  满足条件的子矩阵一共有 191919,包含:
  大小为 1×11 × 11×1 的有 101010 个。
  大小为 1×21 × 21×2 的有 333 个。
  大小为 1×31 × 31×3 的有 222 个。
  大小为 1×41 × 41×4 的有 111 个。
  大小为 2×12 × 12×1 的有 333 个。

【评测用例规模与约定】

  对于 30%30\%30% 的数据,N,M≤20N, M ≤ 20N,M≤20。
  对于 70%70\%70% 的数据,N,M≤100N, M ≤ 100N,M≤100。
  对于 100%100\%100% 的数据,1≤N,M≤500;0≤Aij≤1000;1≤K≤2500000001 ≤ N, M ≤ 500; 0 ≤ A_{i j} ≤ 1000; 1 ≤ K ≤ 2500000001≤N,M≤500;0≤Aij​≤1000;1≤K≤250000000。


矩阵前缀和


  预处理出前缀和数组,然后枚举每一个左上角 (x1,y1)(x_1,y_1)(x1​,y1​),对于每一个左上角枚举出它的右下角 (x2,y2)(x_2,y_2)(x2​,y2​),使用前缀和统计这两点描述的矩阵和是否大于 KKK 并计入答案。

  由于任意 Ai,jA_{i,j}Ai,j​ 非负,故 x2x_2x2​ 增加时,y2y_2y2​ 的取值递减,我们可以维护上个一行的 y2′y_2'y2′​,求出对于每一个 x2x_2x2​ 能取到的最大 y2y_2y2​,由 x1x_1x1​,x2x_2x2​,y2′′y_2''y2′′​,y2′′≤y2y_2'' \leq y_2y2′′​≤y2​ 能确定出的子矩阵数为 y2−y1+1y_2 - y_1 + 1y2​−y1​+1,至此,算法被优化至 O(n3)O(n^3)O(n3)。

  矩阵苦手,极限了兄弟们。

#include <stdio.h>int n, m, k, A[501][501];long long ans;int main() {scanf("%d %d %d", &n, &m, &k);for (int i = 1; i <= n; ++i)for (int j = 1; j <= m; ++j)scanf("%d", &A[i][j]),A[i][j] += A[i - 1][j] + A[i][j - 1] - A[i - 1][j - 1];for (int i = 1; i <= n; ++i)for (int j = 1; j <= m; ++j) {int y = m;for (int x = i; x <= n; ++x) {while (j <= y && A[x][y] - A[i - 1][y] - A[x][j - 1] + A[i - 1][j - 1] > k) --y;if (j > y) break;ans += y - j + 1;}}printf("%lld", ans);
}

试题 G: 积木画

时间限制: 1.0s1.0\mathrm s1.0s 内存限制: 256.0MB256.0\mathrm{MB}256.0MB 本题总分:202020 分


【问题描述】

  小明最近迷上了积木画,有这么两种类型的积木,分别为 III 型(大小为 222 个单位面积)和 LLL 型(大小为 333 个单位面积):::

  同时,小明有一块面积大小为 2×N2 × N2×N 的画布,画布由 2×N2 × N2×N 个 1×11 × 11×1 区域构成。小明需要用以上两种积木将画布拼满,他想知道总共有多少种不同的方式?积木可以任意旋转,且画布的方向固定。

【输入格式】

  输入一个整数 NNN,表示画布大小。

【输出格式】

  输出一个整数表示答案。由于答案可能很大,所以输出其对 100000000710000000071000000007 取模后的值。

【样例输入】

3

【样例输出】

5

【样例说明】
  五种情况如下图所示,颜色只是为了标识不同的积木:::

【评测用例规模与约定】

  对于所有测试用例,1≤N≤100000001 ≤ N ≤ 100000001≤N≤10000000。


状压 DP


  按列划分后,第 iii 列能摆放某个积木是否合法,摆放后的方案数为几何,显然与第 i−1i-1i−1 列有关,于是想到状压 DPDPDP。

  设 fi,(00)2f_{i,(00)_2}fi,(00)2​​、fi,(01)2f_{i,(01)_2}fi,(01)2​​、fi,(10)2f_{i,(10)_2}fi,(10)2​​、fi,(11)2f_{i,(11)_2}fi,(11)2​​,分别为 没有、第 111 行 iii 列、222 行 iii 列、111 行 iii 列 和 222 行 iii 列被某个积木占据的方法数。

  对于在 iii 列上的 III 型积木的直立摆放,我们从 fi−1,3f_{i-1,3}fi−1,3​ 上转移,躺平摆放则分别从 fi−1,1⟶fi,2f_{i-1,1}\longrightarrow f_{i,2}fi−1,1​⟶fi,2​、fi−1,2⟶fi,1f_{i-1,2}\longrightarrow f_{i,1}fi−1,2​⟶fi,1​,最后两个躺着的 III 型积木 fi−1,0⟶fi,3f_{i-1,0} \longrightarrow f_{i,3}fi−1,0​⟶fi,3​。

  对于在 iii 列上的 LLL 型积木的摆放,我们假定 LLL 的朝向为上,此时它需要从 fi−1,0⟶fi,2f_{i-1,0}\longrightarrow f_{i,2}fi−1,0​⟶fi,2​,对于它朝向在 右、下、左 时则分别要从 fi−1,0⟶fi,1f_{i-1,0}\longrightarrow f_{i,1}fi−1,0​⟶fi,1​、fi−1,2⟶fi,3f_{i-1,2}\longrightarrow f_{i,3}fi−1,2​⟶fi,3​、fi−1,1⟶fi,3f_{i-1,1}\longrightarrow f_{i,3}fi−1,1​⟶fi,3​。

  于是有状态转移方程:fi,0=fi−1,3fi,1=fi−1,0+fi−1,2fi,2=fi−1,0+fi−1,1fi,3=fi−1,0+fi−1,1+fi−1,2+fi−1,3\begin{aligned}f_{i,0} &= f_{i-1,3}\\f_{i,1}&=f_{i-1,0} + f_{i-1,2}\\f_{i,2}&=f_{i-1,0} + f_{i-1,1}\\f_{i,3}&=f_{i-1,0}+f_{i-1,1} + f_{i-1,2}+f_{i-1,3}\end{aligned}fi,0​fi,1​fi,2​fi,3​​=fi−1,3​=fi−1,0​+fi−1,2​=fi−1,0​+fi−1,1​=fi−1,0​+fi−1,1​+fi−1,2​+fi−1,3​​  但其实根本不需要这么多状态,因为 fi,0f_{i,0}fi,0​ 可以直接由 fi−1,3f_{i-1,3}fi−1,3​ 确定,而将状态 (01)2(01)_2(01)2​ 的摆放法垂直翻转后就能得到状态为 (10)2(10)_2(10)2​ 的方案数,由此我们可以得出结论对于任意 iii 都有 fi,1=fi,2f_{i,1} = f_{i,2}fi,1​=fi,2​,依此为基础进一步优化状态转移方程:

  fi,1=fi−2,3+fi−1,1=fi−2,3+fi−3,3+fi−2,1=fi−2,3+fi−3,3+⋯+f0,3+f1,1=∑j=0i−2fj,3\begin{aligned}f_{i,1} &= f_{i-2,3} + f_{i-1,1}\\&=f_{i-2,3}+f_{i-3,3}+f_{i-2,1}\\&=f_{i-2,3}+f_{i-3,3}+\cdots+f_{0,3}+f_{1,1}\\&=\sum_{j=0}^{i-2} f_{j,3}\end{aligned}fi,1​​=fi−2,3​+fi−1,1​=fi−2,3​+fi−3,3​+fi−2,1​=fi−2,3​+fi−3,3​+⋯+f0,3​+f1,1​=j=0∑i−2​fj,3​​

  将 fi,3f_{i,3}fi,3​ 变化符号为 fif_ifi​,又 f1,1f_{1,1}f1,1​ 显然等于 000,故有:

  fi,1=∑j=0i−2fjf_{i,1} =\sum_{j=0}^{i-2} f_{j}fi,1​=∑j=0i−2​fj​

  fi=∑j=0i−1fj+∑j=0i−3fjf_i =\sum_{j=0}^{i-1} f_{j} + \sum_{j=0}^{i-3} f_{j}fi​=∑j=0i−1​fj​+∑j=0i−3​fj​

  fi−fi−1=∑j=0i−1fj−∑j=0i−2fj+∑j=0i−3fj−∑j=0i−4fj=fi−1+fi−3\begin{aligned}f_i - f_{i-1}&=\sum_{j=0}^{i-1} f_{j} - \sum_{j=0}^{i-2} f_{j} + \sum_{j=0}^{i-3} f_{j} - \sum_{j=0}^{i-4} f_{j}\\&=f_{i-1} + f_{i-3}\end{aligned}fi​−fi−1​​=j=0∑i−1​fj​−j=0∑i−2​fj​+j=0∑i−3​fj​−j=0∑i−4​fj​=fi−1​+fi−3​​
  最终fi=2fi−1+fi−3f_i=2f_{i-1} + f_{i-3}fi​=2fi−1​+fi−3​  初始时 f0=1f_{0} = 1f0​=1,f1=1f_1=1f1​=1,f2=2f_2=2f2​=2,答案为 fnf_nfn​。

  草,不该推这个式子的,

  浪费时间。

#include <stdio.h>int n, p = 1000000007, dp[10000010] = {1, 1, 2};int main() {scanf("%d", &n);for (int i = 3; i <= n; ++i)dp[i] = (2ll * dp[i - 1] + dp[i - 3]) % p;printf("%d", dp[n]);
}

试题 H: 扫雷

时间限制: 1.0s1.0\mathrm s1.0s 内存限制: 256.0MB256.0\mathrm{MB}256.0MB 本题总分:202020 分


【问题描述】

  小明最近迷上了一款名为《扫雷》的游戏。其中有一个关卡的任务如下,在一个二维平面上放置着 nnn 个炸雷,第 iii 个炸雷 (xi,yi,ri)(x_i, y_i, r_i)(xi​,yi​,ri​) 表示在坐标 (xi,yi)(x_i, y_i)(xi​,yi​) 处存在一个炸雷,它的爆炸范围是以半径为 rir_iri​ 的一个圆。

  为了顺利通过这片土地,需要玩家进行排雷。玩家可以发射 mmm 个排雷火箭,小明已经规划好了每个排雷火箭的发射方向,第 jjj 个排雷火箭 (xj,yj,rj)(x_j, y_j, r_j)(xj​,yj​,rj​) 表示这个排雷火箭将会在 (xj,yj)(x_j , y_j)(xj​,yj​) 处爆炸,它的爆炸范围是以半径为 rjr_jrj​ 的一个圆,在其爆炸范围内的炸雷会被引爆。同时,当炸雷被引爆时,在其爆炸范围内的炸雷也会被引爆。现在小明想知道他这次共引爆了几颗炸雷?

  你可以把炸雷和排雷火箭都视为平面上的一个点。一个点处可以存在多个炸雷和排雷火箭。当炸雷位于爆炸范围的边界上时也会被引爆。

【输入格式】

  输入的第一行包含两个整数 n、mn、mn、m。

  接下来的 nnn 行,每行三个整数 xi,yi,rix_i, y_i, r_ixi​,yi​,ri​,表示一个炸雷的信息。

  再接下来的 mmm 行,每行三个整数 xj,yj,rjx_j, y_j, r_jxj​,yj​,rj​,表示一个排雷火箭的信息。

【输出格式】

  输出一个整数表示答案。

【样例输入】

2 1
2 2 4
4 4 2
0 0 5

【样例输出】

2

【样例说明】
  示例图如下,排雷火箭 111 覆盖了炸雷 111,所以炸雷 111 被排除;炸雷 111 又覆盖了炸雷 222,所以炸雷 222 也被排除。


【评测用例规模与约定】

  对于 40%40\%40% 的评测用例:0≤x,y≤109,0≤n,m≤103,1≤r≤10:0 ≤ x, y ≤ 10^9, 0 ≤ n, m ≤ 10^3, 1 ≤ r ≤ 10:0≤x,y≤109,0≤n,m≤103,1≤r≤10。
  对于 100%100\%100% 的评测用例:0≤x,y≤109,0≤n,m≤5×104,1≤r≤10:0 ≤ x, y ≤ 10^9, 0 ≤ n, m ≤ 5 × 10^4, 1 ≤ r ≤ 10:0≤x,y≤109,0≤n,m≤5×104,1≤r≤10。


BFS


  将排雷火箭视为一个地雷 (x,y,r)(x,y,r)(x,y,r),只是不计入答案数,然后对每一个排雷火箭进行广搜,搜索 (x−r,y−r),(x+r,y+r)(x-r,y-r),(x+r,y+r)(x−r,y−r),(x+r,y+r) 确定的矩形中,满足 (x′−x)2+(y′−y)2≤r\sqrt{(x'-x)^2+(y'-y)^2} \leq r(x′−x)2+(y′−y)2​≤r 且存在地雷的点,统计答案然后加入到队列中,直至队列为空,避免出现精度丢失问题我们对不等式两边平方。

  dotcpp 上的数据卡了常数,map\mathrm{map}map 写我过不去,得把 X,YX,YX,Y 离散化了。

#include <stdio.h>
#include <algorithm>
#include <queue>struct mine {int x, y, r, i;
} mines[50010], *sorted_byx[50010], *sorted_byy[50010], **xl, **xr, **yl, **yr;inline bool cmp_byx(const mine *m1, const mine *m2) { return m1->x < m2->x; }inline bool cmp_byy(const mine *m1, const mine *m2) { return m1->y < m2->y; }inline bool mine_on_circle(mine *m, int x, int y, int r) { return (long long)(m->x - x) * (m->x - x) + (long long)(m->y - y) * (m->y - y) <= r * r; }int n, m, x, y, r, ans;std::queue<int> queue;bool visited[50010];int main() {scanf("%d %d", &n, &m);for (int i = 0; i < n; ++i)scanf("%d %d %d", &mines[i].x, & mines[i].y, &mines[i].r),mines[i].i = i, sorted_byx[i] = sorted_byy[i] = &mines[i];std::sort(sorted_byx, sorted_byx + n, cmp_byx);std::sort(sorted_byy, sorted_byy + n, cmp_byy);for (int i = 0; i < m; ++i) {scanf("%d %d %d", &mines[n].x, & mines[n].y, &mines[n].r);queue.push(n);while (queue.size()) {x = mines[queue.front()].x;y = mines[queue.front()].y;r = mines[queue.front()].r, queue.pop();mines[n].x = x - r, xl = std::lower_bound(sorted_byx, sorted_byx + n, &mines[n], cmp_byx);mines[n].y = y - r, yl = std::lower_bound(sorted_byy, sorted_byy + n, &mines[n], cmp_byy);mines[n].x = x + r + 1, xr = std::upper_bound(sorted_byx, sorted_byx + n, &mines[n], cmp_byx);mines[n].y = y + r + 1, yr = std::upper_bound(sorted_byy, sorted_byy + n, &mines[n], cmp_byy);for (; xl < xr; ++xl)if (!visited[(*xl)->i] && mine_on_circle(*xl, x, y, r))visited[(*xl)->i] = 1, ++ans, queue.push((*xl)->i);for (; yl < yr; ++yl)if (!visited[(*yl)->i] && mine_on_circle(*yl, x, y, r))visited[(*yl)->i] = 1, ++ans, queue.push((*yl)->i);}}printf("%d", ans);
}

  指针乱飞但拒不改正。


试题  I: 李白打酒加强版

时间限制: 1.0s1.0\mathrm s1.0s 内存限制: 256.0MB256.0\mathrm{MB}256.0MB 本题总分:252525 分


【问题描述】

  话说大诗人李白,一生好饮。幸好他从不开车。

  一天,他提着酒壶,从家里出来,酒壶中有酒 222 斗。他边走边唱:::

  无事街上走,提壶去打酒。
  逢店加一倍,遇花喝一斗。

  这一路上,他一共遇到店 NNN 次,遇到花 MMM 次。已知最后一次遇到的是花,他正好把酒喝光了。

  请你计算李白这一路遇到店和花的顺序,有多少种不同的可能?

  注意:壶里没酒 ( 000 斗) 时遇店是合法的,加倍后还是没酒;但是没酒时遇花是不合法的。

【输入格式】

  第一行包含两个整数 NNN 和 MMM。

【输出格式】

  输出一个整数表示答案。由于答案可能很大,输出模 100000000710000000071000000007 的结果。

【样例输入】

5 10

【样例输出】

14

【样例说明】
  如果我们用 0 代表遇到花,1 代表遇到店,14 种顺序如下:::
010101101000000010110010010000011000110010000100010110010000011001000110000100011000110000100100010110000010110100000100011001001000100100011001000100100100011000100011010000010100100100100010100101000001010100\qquad010101101000000\\\qquad010110010010000\\\qquad011000110010000\\\qquad100010110010000\\\qquad011001000110000\\\qquad100011000110000\\\qquad100100010110000\\\qquad010110100000100\\\qquad011001001000100\\\qquad100011001000100\\\qquad100100011000100\\\qquad011010000010100\\\qquad100100100010100\\\qquad101000001010100010101101000000010110010010000011000110010000100010110010000011001000110000100011000110000100100010110000010110100000100011001001000100100011001000100100100011000100011010000010100100100100010100101000001010100

【评测用例规模与约定】

  对于 40%40\%40% 的评测用例:1≤N,M≤10:1 ≤ N, M ≤ 10:1≤N,M≤10。
  对于 100%100\%100% 的评测用例:1≤N,M≤100:1 ≤ N, M ≤ 100:1≤N,M≤100。


动态规划


  当壶中酒的斗数大于 mmm 时,无论如何都无法使酒喝光,于是限制其上限为 mmm,考虑动态规划。

  设 fi,j,kf_{i,j,k}fi,j,k​ 为李白在经过 iii 家店和遇 jjj 次花后使得酒还剩 kkk 斗的方案数。

  若李白此刻遇花,则有 fi,j,k=fi,j−1,k+1f_{i,j,k} = f_{i,j-1,k+1}fi,j,k​=fi,j−1,k+1​。

  若李白此刻进店,则考虑 kkk 是否为 222 的倍数,若是将 fi,j,kf_{i,j,k}fi,j,k​ 累加上一个 fi−1,j,k2f_{i-1,j,\frac k2}fi−1,j,2k​​。

  最后特判一下很麻烦,索性就输出 fn,m−1,1f_{n,m-1,1}fn,m−1,1​ 了。

  关于提醒无酒进店是合法的其实我没看太懂,因为最后一刻要求遇花且恰把酒喝完,而出现无酒后无论如何都无法达到一个剩余一定的酒且遇花合法的状态,关键这作为压轴题也太简单的离谱了。

  蓝桥,看不透。

#include <stdio.h>int n, m, p = 1000000007, dp[101][101][101]= { 0, 0, 1};int main() {scanf("%d %d", &n, &m);for (int i = 0; i <= n; ++i)for (int j = 0; j < m; ++j)for (int k = 1; k <= m; ++k) {if (i && k % 2 == 0) dp[i][j][k] = dp[i - 1][j][k / 2];if (j) dp[i][j][k] = (dp[i][j][k] + dp[i][j - 1][k + 1]) % p;}printf("%d", dp[n][m - 1][1]);
}

试题 J: 砍竹子

时间限制: 1.0s1.0\mathrm s1.0s 内存限制: 256.0MB256.0\mathrm{MB}256.0MB 本题总分:252525 分


【问题描述】

  这天,小明在砍竹子,他面前有 nnn 棵竹子排成一排,一开始第 i 棵竹子的高度为 hih_ihi​。

  他觉得一棵一棵砍太慢了,决定使用魔法来砍竹子。魔法可以对连续的一段相同高度的竹子使用,假设这一段竹子的高度为 HHH,那么使用一次魔法可以把这一段竹子的高度都变为 ⌊⌊H2⌋+1⌋\lfloor\sqrt{\lfloor\frac H2\rfloor + 1}\rfloor⌊⌊2H​⌋+1​⌋,其中 ⌊x⌋\lfloor x\rfloor⌊x⌋ 表示对 xxx 向下取整。小明想知道他最少使用多少次魔法可以让所有的竹子的高度都变为 111。

【输入格式】

  第一行为一个正整数 nnn,表示竹子的棵数。

  第二行共 nnn 个空格分开的正整数 hih_ihi​,表示每棵竹子的高度。

【输出格式】

  一个整数表示答案。

【样例输入】

6
2 1 4 2 6 7

【样例输出】

5

【样例说明】
  其中一种方案:::
  2142672\ 1\ 4\ 2\ 6\ 72 1 4 2 6 7
  →214262\rightarrow 2\ 1\ 4\ 2\ 6\ 2→2 1 4 2 6 2
  →214222\rightarrow 2\ 1\ 4\ 2\ 2\ 2→2 1 4 2 2 2
  →211222\rightarrow 2\ 1\ 1\ 2\ 2\ 2→2 1 1 2 2 2
  →111222\rightarrow 1\ 1\ 1\ 2\ 2\ 2→1 1 1 2 2 2
  →111111\rightarrow 1\ 1\ 1\ 1\ 1\ 1→1 1 1 1 1 1
  共需要 555 步完成

【评测用例规模与约定】

  对于 20%20\%20% 的数据,保证 n≤1000,hi≤106n ≤ 1000, h_i ≤ 10^6n≤1000,hi​≤106。
  对于 100%100\%100% 的数据,保证 n≤2×105,hi≤1018n ≤ 2 × 10^5, hi ≤ 10^{18}n≤2×105,hi≤1018。


  想起那年国赛,压轴题 O(nlog⁡n)O(n\log n)O(nlogn) 的贪心排序,n≤1e3n \leq 1e3n≤1e3,时间限制给了 333 秒。

  就很会你知道吧。


贪心


  如果一排最大连续的竹子高度相同且高度不为 111,那么在一个可行的最优解中,一定存在有若干次魔法包含这一排竹子,简单证明一下:

  设这排竹子在 [i,j][i,j][i,j] 上最大连续,若有一次魔法不是将它们全部包含,设魔法的操作区间为 [x,y][x,y][x,y],因为 [i,j][i,j][i,j] 的最大性,[x,y][x,y][x,y] 一定被它们包含,若 [x,y][x,y][x,y] 没有落在端点上,则这次魔法对 [1,i)[1,i)[1,i)、(j,n](j,n](j,n] 没有贡献一定不优,否则对将来出现的包含 [x,y][x,y][x,y] 的操作 [k,g][k,g][k,g] 全部转为 [k,i)[k,i)[k,i),现在的 [x,y][x,y][x,y] 跟随 [i,j][i,j][i,j] 一起变化,答案一定不会变少。

  并且一个高度只受变化公式的影响而与魔法顺序无关。

  容易想到贪心策略,即:

  建立一个优先队列将连续的一排竹子加入进去。

  每次取出最高的竹子,并检查列队剩余的竹子是否能加入到这一排中,然后对其释放魔法,最后回到该步开头直至队列为空。

  写的真粪

#include <stdio.h>
#include <math.h>
#include <queue>struct Node {int l, r;long long h;Node(int l1, int r1, long long h1) : l(l1), r(r1), h(h1) {}inline bool operator<(const Node &n) const { return h == n.h ? l > n.l : h < n.h; }
};std::priority_queue<Node> q;long long h;int n, ans;int main() {scanf("%d", &n);for (int i = 1; i <= n; ++i)scanf("%lld", &h), q.push(Node(i, i, h));while (q.size()) {if (q.top().h == 1) break;Node now = q.top();q.pop();while (q.size() && q.top().h == now.h && q.top().l == now.r + 1)now.r = q.top().r, q.pop();++ans;now.h = sqrt(now.h / 2 + 1);if (now.h > 1) q.push(now);}printf("%d", ans);
}

  又卡常数又考贪心,

  什么 ∗∗**∗∗ 出的题。

第十三届蓝桥杯大赛软件赛省赛(C/C++ 大学B组)相关推荐

  1. 2022年第十三届蓝桥杯大赛软件类国赛 C/C++ 大学B组

    试题 A: 2022 #include<bits/stdc++.h> using namespace std;typedef long long LL; LL dp[11][2023];i ...

  2. 第十三届蓝桥杯大赛软件类国赛 C/C++ 大学B组 试题 G: 故障

    试题 G: 故障 贝叶斯公式 条件概率的运用,即发生A事件的条件下,B事件发生的概率. #include<cstdio> #include<cmath> #include< ...

  3. 第十三届蓝桥杯大赛软件赛省赛真题

    第十三届蓝桥杯大赛软件赛省赛Java 大学 B 组 文章目录 第十三届蓝桥杯大赛软件赛省赛Java 大学 B 组 [考生须知] 试题 A: 星期计算 试题 B: 山 试题 C: 字符统计 试题 D: ...

  4. 第十三届蓝桥杯大赛软件赛省赛 Python 大学 B 组

    第十三届蓝桥杯大赛软件赛省赛 Python 大学 B 组 第十三届蓝桥杯大赛软件赛省赛 Python 大学 B 组 [考生须知] 考试开始后,选手首先下载题目,并使用考场现场公布的解压密码解压试 题. ...

  5. 第十三届蓝桥杯大赛软件赛省赛(b组c语言)

    试题 A: 九进制转十进制 本题总分:5 分 [问题描述] 九进制正整数 (2022)9 转换成十进制等于多少? 这道题没什么说的,2*9*9*9+0*9*9+2*9+2*1=1478: 试题 B: ...

  6. 2022年第十三届蓝桥杯大赛软件省赛Java学B组试题

    第十三届蓝桥杯大赛软件省赛Java学B组试题 一.试题截图 1. 星期计算 这道题是可以直接用笔算起来的,我算出来的答案是5,(2022整除7 余6,六天后就是星期五)但目前官方答案还不知道是什么? ...

  7. 2022年蓝桥杯:第十三届蓝桥杯大赛软件赛省赛C/C++大学B组真题(考后回顾,文末附真题链接)

    目录 第十三届蓝桥杯大赛软件赛省赛C/C++大学B组真题(考后回顾) 试题 A: 九进制转十进制 试题 B: 顺子日期 试题 C: 刷题统计 试题 D: 修剪灌木 试题 E: X 进制减法 试题 F: ...

  8. 第十三届蓝桥杯大赛软件赛省赛 Java 研究生组

    第十三届蓝桥杯大赛软件赛省赛 Java 研究生组 [考生须知] 考试开始后,选手首先下载题目,并使用考场现场公布的解压密码解压试 题. 考试时间为 4 小时.考试期间选手可浏览自己已经提交的答案,被浏 ...

  9. 第十三届蓝桥杯大赛软件赛省赛 Python 大学 C 组

    试题 A: 排列字母 本题总分:5 分 [问题描述] 小蓝要把一个字符串中的字母按其在字母表中的顺序排列. 例如,LANQIAO 排列后为 AAILNOQ. 又如,GOODGOODSTUDYDAYDA ...

  10. 第十三届蓝桥杯大赛软件赛决赛C组C++

    试题 A: 斐波那契与 7 本题总分:5 分 [问题描述] 斐波那契数列的递推公式为:Fn = Fn−1 + Fn−2,其中 F1 = F2 = 1. 请问,斐波那契数列的第 1 至 20220201 ...

最新文章

  1. Cobalt Strike 的安装与简单使用
  2. Java,Hello world 欢迎进入Java世界
  3. 寻找带环的链表的柄长
  4. Django model查询之F,Q操作
  5. IOS Core Animation Advanced Techniques的学习笔记(五)
  6. Cetos 7 系统安装备注事项
  7. Skype现已支持开源VP8视频编解码器
  8. 习题3.8 符号配对 (20分)
  9. MYSQL数据库表操作pdf
  10. innodb_flush_log_at_trx_commit和sync_binlog参数详解
  11. QQ群会员彩色昵称代码
  12. Word VBA-表格操作汇总
  13. 5000个常用汉字(完整版) 繁体简体
  14. 17.分段函数、绝对值函数以及幂指函数求导
  15. 【大神】用ESP32自制WiFi版高清语音电话产品WiPhone,WiPhone电话应用电话小车
  16. 【高并发】一文解密诡异并发问题的第一个幕后黑手——可见性问题
  17. 蓝牙耳机按键事件linux,【记录】Android监听蓝牙耳机的按键事件
  18. 第一个iOS应用 —— Hello world!
  19. c语言strtok用法详细解释
  20. 西安三日游-梦回长安

热门文章

  1. android studio教程,Android Studio一个完整的APP实例
  2. 石英晶体谐振器的功能有哪些
  3. python 读取合并单元格的数据_Python使用xlrd实现读取合并单元格
  4. Hadoop与workflow入门
  5. 让电脑速度快上100%方法
  6. 淘宝网站简易分析评价
  7. C语言--独立的大括号{}
  8. java Steam流的用法
  9. 多模态视觉任务Video Grounding介绍
  10. jsvmp-某乎_x-zes-96参数算法还原(手把手教学)