2024 蓝桥杯模拟赛3(div1+div2)

1|0P8834 [传智杯 #3 决赛] 序列


O(N2)枚举

def read(): return map(int, input().split()) n, k = read() a = list(read()) res = 0 for i in range(n): for j in range(i): if a[i] * a[j] <= k: res += 1 print(res)

2|0P8780 [蓝桥杯 2022 省 B] 刷题统计


数据很弱可以直接枚举

def read(): return map(int, input().split()) a, b, n = read() l = [a, a, a, a, a, b, b] cnt, t, res = 0, 0, 0 while cnt < n: cnt += l[t] t = (t + 1) % 7 res += 1 print(res)

当然比较保险的做法是算出一周的做题数,然后除一下

3|0P8623 [蓝桥杯 2015 省 B] 移动距离


要把变换转换为坐标,然后计算曼哈顿距离。要注意偶数行的话要把纵坐标倒过来

def read(): return map(int, input().split()) w, n, m = read() n -= 1 m -= 1 nx, ny = n // w, n % w if nx % 2 == 1: ny = w - 1 - ny mx, my = m // w, m % w if mx % 2 == 1: my = w - 1 - my print(abs(nx - mx) + abs(ny - my))

4|0P8738 [蓝桥杯 2020 国 C] 天干地支


直接打表,然后计算一下偏移量

tian = ["jia", "yi", "bing", "ding", "wu", "ji", "geng", "xin", "ren", "gui"] di = ["zi", "chou", "yin", "mao", "chen", "si", "wu", "wei", "shen", "you", "xu", "hai"] n = int(input()) print(tian[(n + 6) % 10], di[(n + 8) % 12], sep="")

5|0P8635 [蓝桥杯 2016 省 AB] 四平方和


枚举三个平方数,然后计算第四个平方数,有解直接输出

import math n = int(input()) m = int(math.sqrt(n)) for i in range(m): if i ** 2 > n: break a = i * i for j in range(i, m): if a + j ** 2 > n: break b = j ** 2 for k in range(j, m): if a + b + k ** 2 > n: break c = k ** 2 d = n - a - b - c if d < c: break l = int(math.sqrt(d)) if l ** 2 == d: print(i, j, k, l) exit()

6|0P8697 [蓝桥杯 2019 国 C] 最长子序列


直接贪心从前向后匹配即可,但是注意如果采用整行读入的做法,末尾疑似有多余的空格。

s, t = input(), input() while s[-1] < 'A' or s[-1] > 'Z': s = s[0: -1] while t[-1] < 'A' or t[-1] > 'Z': t = t[0: -1] res = 0 for i in s: if res >= len(t): break if i == t[res]: res += 1 print(res)

7|0P8654 [蓝桥杯 2017 国 C] 合根植物


这题并不需要转换坐标,直接采用并查集合并即可

class dsu: fa = list() def __init__(self, n): self.fa = [-1 for i in range(n + 1)] def find(self, n): if self.fa[n] < 0: return n self.fa[n] = self.find(self.fa[n]) return self.fa[n] def union(self, x, y): x = self.find(x) y = self.find(y) if x == y: return if self.fa[x] > self.fa[y]: x, y = y, x self.fa[x] += self.fa[y] self.fa[y] = x def root(self, x): return x == self.find(x) def read(): return map(int, input().split()) n, m = read() N = n * m d = dsu(N) k = int(input()) for i in range(k): a, b = read() d.union(a, b) res = 0 for i in range(1, N + 1): res += d.root(i) print(res)

8|0P9421 [蓝桥杯 2023 国 B] 班级活动


首先统计每种人名使用的次数

如果一种名字使用次数等于2,则不用操作

如果一种名字使用次数大于2,则大于2的部分都需要改名,把这部分和记为res

如果一种名字使用次数小于2,也就是等于1,不一定需要改名,先把这部分的和记为ans

我们来考虑最优解是什么?最优解一定是把res部分的名字修改为ans,然后把剩下的ansres其中一半修改为另一半

所以答案就是res+max(ansres2,0)

def read(): return map(int, input().split()) cnt = dict() n = int(input()) for i in read(): if i in cnt: cnt[i] += 1 else: cnt[i] = 1 res, ans = 0, 0 for i in cnt.keys(): if cnt[i] >= 2: res += cnt[i] - 2 elif cnt[i] == 1: ans += 1 print(res + max(ans - res, 0) // 2)

9|0P8604 [蓝桥杯 2013 国 C] 危险系数


因为点和边都不多,所以直接枚举删掉一个点,然后用并查集维护一下连通性,然后判断u,v是否联通,如果不连通,则删掉的点就是关键点

class dsu: fa = list() def __init__(self, n): self.fa = [-1 for i in range(n + 1)] def find(self, n): if self.fa[n] < 0: return n self.fa[n] = self.find(self.fa[n]) return self.fa[n] def union(self, x, y): x = self.find(x) y = self.find(y) if x == y: return if self.fa[x] > self.fa[y]: x, y = y, x self.fa[x] += self.fa[y] self.fa[y] = x def root(self, x): return x == self.find(x) def same(self, x, y): x = self.find(x) y = self.find(y) return x == y def read(): return map(int, input().split()) n, m = read() edge = [[] for i in range(m)] for i in range(m): edge[i] = list(read()) u, v = read() res = 0 for z in range(1, n + 1): if z == u or z == v: continue d = dsu(n) for it in edge: if it[0] == z or it[1] == z: continue d.union(it[0], it[1]) if (d.same(u, v)): continue res += 1 print(res)

10|0P8692 [蓝桥杯 2019 国 C] 数正方形


首先我们把点转换成段

image-20240226173257039.png

然后手画一下就会发现,有几段的矩形内部就有几种矩形,所以我们可以枚举一下矩形的大小,然后计算一下当前大小的矩形有多少个即可。

Mod = int(1e9 + 7) n = int(input()) - 1 res = 0 for i in range(1, n + 1): res = (res + i * (n - i + 1) ** 2) % Mod print(res)

11|0P9232 [蓝桥杯 2023 省 A] 更小的数


11|140 分


首先最简单的方法就是暴力,直接枚举区间然后翻转比较一下

s = input() n = len(s) res = 0 for i in range(n): for j in range(i + 1, n): t = s[0: i] + s[i: j + 1][::-1] + s[j + 1:n] if t < s: res += 1 print(res)

11|2100 分


正解是区间dp

其实我们还是要暴力的枚举区间,我们考虑如何快速判断区间是否合法

我们枚举的区间是[l,r]

  1. 如果sl>sr,则翻转后一定会更小
  2. 如果sl<sr,则翻转后一定会更大
  3. 如果sl=sr,则是否合法取决于[l+1,r1]

从小到达枚举区间,然后计算并统计合法区间数量即可

s = input() n = len(s) f = [[0 for i in range(n)] for j in range(n)] res = 0 for len in range(1, n): l, r = 0, len while r < n: if s[l] > s[r]: f[l][r] = 1 elif s[l] == s[r]: f[l][r] = f[l + 1][r - 1] res += f[l][r] l, r = l + 1, r + 1 print(res)

12|0P8756 [蓝桥杯 2021 省 AB2] 国际象棋


这其实算是状压dp的模板题了

从左往右依次放置,因此只考虑右侧的列即可。

假设(x,y)的位置有马,则(x+2,y1),(x2)(y1),(x+1,y2),(x1,y2)都不能放置,因此我要知道当前列是否合法只需要知道上一列和上上一列即可。

因为行很少,我们可以用一个六位二进制数表示一列的情况。

设状态为f[i][j][a][b]表示前i列累计放置j个,且第i列状态为b、第i1列状态为a,这样只需枚举i,j以及最后三列a,b,c的状态即可判断是否可以进行转移。

为了方便计算,可以预处理val[x]表示每种状态下,这一列放置了多少个。

如果(b>>2)&c + (b<<2)&c == 0成立,则说明第i列和第i1列不冲突。

如果(a>>1)&c + (a<<1)&c == 0成立,则说明第i列和第i1列不冲突。

如果(b>>2)&a + (b<<2)&a == 0成立,则说明第i2列和第i1列不冲突。

如果val[a]+val[b]+val[c] <= j,则数量是合法的

如果上述都满足,则有转移f[i][j][b][c] += f[i-1][j-val[c]][a][b]

def read(): return map(int, input().split()) n, m, k = read() N = (1 << n) Mod = int(1e9 + 7) val = [0] * N for i in range(N): x = i while x > 0: val[i] += x % 2 x //= 2 if m == 1: res = 0 for i in range(N): if val[i] == k: res += 1 print(res) exit(0) f = [[[[0 for i in range(N)] for i in range(N)] for i in range(k + 1)] for i in range(m)] for a in range(N): if val[a] > k: continue for b in range(N): if val[a] + val[b] > k: continue if (a << 2) & b != 0 or (a >> 2) & b != 0: continue f[1][val[a] + val[b]][a][b] = 1 for i in range(2, m): for j in range(k + 1): for a in range(N): if val[a] > j: continue for b in range(N): if val[a] + val[b] > j: continue if (a << 2) & b != 0 or (a >> 2) & b != 0: continue for c in range(N): if val[a] + val[b] + val[c] > j: continue if (b << 2) & c != 0 or (b >> 2) & c != 0: continue if (a << 1) & c != 0 or (a >> 1) & c != 0: continue f[i][j][b][c] = (f[i][j][b][c] + f[i - 1][j - val[c]][a][b]) % Mod res = 0 for a in range(N): for b in range(N): res = (res + f[m - 1][k][a][b]) % Mod print(res)

该说不说,python开数组还是挺抽象的


__EOF__

本文作者PHarr
本文链接https://www.cnblogs.com/PHarr/p/18034877.html
关于博主:前OIer,SMUer
版权声明CC BY-NC 4.0
声援博主:如果这篇文章对您有帮助,不妨给我点个赞
posted @   PHarr  阅读(154)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示