2026蓝桥省pyb补题及吐槽
2026蓝桥省pyb补题及吐槽
26蓝桥pyb
碎叨叨
打车到赛点已经晕死,依旧忘记吃买的面包,依旧忘记吃药,依旧打满4h
A题很简单暴力模拟即可,B题看了一眼纯暴力要花大概14亿天,直接跳了
C题读完题目想着这个位置不就是给我打暴力的吗,直接两个for循环(GG)…
D题读完题目感觉像DP,模拟了几个列子,不太可做,DFS写了暴力 (幸好没做,是蓝题)
E题读完当场直接蒙了一个尼莫博弈 ~~(巴巴博弈),应该是暴0了 ~~???
F看题目应该是并查集,但是比较复杂,不是板子题 ~~(板子我也忘记了),直接模拟了,拿了应该40%(赚大了)~~
GH直接暴力,G题目很长,有点复杂,H就很容易暴力了,拿了各40%
暴力专场,A~H可做的都做错了 ~~(活该hhhh)+不可做的全部DFS混分 == 省一(国赛当然也是打暴力了)~~
难度 (个人感觉…)
Easy: A、B 、C
Mid: E、G、F
Hard: H、D
D不可做 补不了,,,,FGH前置知识有点多,暂时学不会(悲)
-
A-模拟
P16260 [蓝桥杯 2026 省 Python/Java B 组] 和平干饭日 - 洛谷
直接暴力即可
(毫无新意)暴力 from sys import *set_int_max_str_digits(0)cnt=0x=''for i in range(1,2027):x+=str(i)x=int(x)if x%26==0:cnt+=1x=str(x)print(cnt) -
B-数学
P16261 [蓝桥杯 2026 省 Python/Java B 组] 干涉条纹 - 洛谷
特有的B题考数学思维…
(我的数学思维呢???)题意:
有两个区间各选一个整数出来后,要使得 是一个完全平方数,求方案数。
其中。
题解:
显然暴力是不可做的,区间太大了
换个角度,通过枚举比较少的完全平方数,从0枚举到A+B,
问题转换为:给定完全平方数S,在两个区间中各选择一个数子,加起来等于等于S有对少种选法。由于S固定,a固定后,b也固定,求a的选法即可。
由和,有:
数学 MOD = 998244353ans = 0A = 20269876543210B = 20260123456789i = 0while i * i <= A + B:s = i * il = max(0,s - B)r = min(s,A)ans += max(0,r - l + 1)ans %= MODi += 1print(ans) -
C-合数
P16262 [蓝桥杯 2026 省 Python B 组] 定制展示盘 - 洛谷
赛时两个for真的丑完了…
总槽位数量要大于 n 且行数不能等于1,也就是说这个最小数,一定会被大于或等于 2 的数整除,这时我们就会发现,这个最小数一定不是质数,所以我们要求的是不小于 n 且不是质数的最小数,亦即找到一个不小于n的合数。
1.由于都不小于2,答案不小于4
2.如果本身是不小于4的偶数,则本身就是答案
3.是一个不小于4的奇数,则一定可以
4.答案不会超过,但不一定是答案,列如;
5.从2开始枚举到,验证n能否写出
数学 import math# 求不小于n且不是质数的最小数for _ in range(int(input())):n = int(input())ans = n + (n % 2)for i in range(2,math.isqrt(n) + 1):if n%i:continueans = nbreakans = max(ans,4)print(ans) -
E-博弈
P16264 [蓝桥杯 2026 省 Python B 组] 奇偶博弈 - 洛谷
一道博弈题目,赛时直接写了尼莫博弈,
大错特错()证明很困难,直接贴一个证明链接:
P16264 [蓝桥杯 2026 省 Python B 组] 奇偶博弈 - 洛谷
结论是如果数据中”1”的个数为奇数则输出L,和我一起参赛的朋友找出来了这个规律,TQL!!
证明太困难,不太会,
记结论惹(哭)关键在于本题中”1”没有博弈点,其本质是交换先后手,当”1”全部被处理后,局面变成了在所有非”1”且全奇数的局面来博弈,
如果你是先手,
你只能把a减1,然后a变成了偶数,对方把该数变成0,这个数就不存在了,你又变成了先手,局面与前者又相同
所以显然的结论:如果 1 有奇数个,则先手必胜;反之先手必败
博弈 for _ in range(int(input())):n = int(input())a = list(map(int,input().split()))cnt = a.count(1)if cnt % 2 == 1:print("L")else:print("Q") -
F-并查集/启发式合并
P16265 [蓝桥杯 2026 省 Python B 组] 蓝小圈 - 洛谷
非板子题,有点困难,CF1800+分
难点在于命令2和3,即在于当集合合并时怎么做到使原来集合整体操作互不干扰
用O(n)查询会超时,过40%
解决困难点的方法是按秩合并
(不太会)(有时间学一学)赛时模拟 n,q = map(int,input().split())t = [set() for i in range(n)]res = [0]*nfor i in range(q):a = list(map(int,input().split()))z,x = a[0],a[1]if z == 1:y = a[2]t[y-1].add(x-1)elif z == 2:y = a[2]res[x-1] += yelif z == 3:y = a[2]res[x-1] += yfor c in t[x-1]:res[c] += yelse:print(res[x-1])并查集板子On做法-40% def find(p,x):if p[x] != x:p[x] = find(p,p[x])return p[x]def union(p,rank,x,y):rx,ry = find(p,x),find(p,y)if rx == ry:returnif rank[rx] < rank[ry]:p[rx] = p[ry]elif rank[rx] > rank[ry]:p[ry] = p[rx]else:p[ry] = p[rx]rank[rx] += 1def main():n,q = map(int,input().split())p = list(range(n+1))res = [0]*(n+1)rank = [1]*(n+1)for _ in range(q):a = list(map(int,input().split()))z,x = a[0],a[1]if z == 1:y = a[2]union(p,rank,x,y)elif z == 2:y = a[2]res[x] += yelif z == 3:y = a[2]for c in range(1,n+1):if find(p,x) == find(p,c):res[c] += yelse:print(res[x])if __name__ == "__main__":main()按秩合并 import sysdef main():input = sys.stdin.readlinen, q = map(int, input().split())fa = list(range(n + 1))sz = [1] * (n + 1)w = [0] * (n + 1) # 路径上的累加值v = [0] * (n + 1) # 节点单独加的值def find(x):while x != fa[x]:x = fa[x]return xdef get(x):# 获取节点 x 所在集合的根节点的 w 累加值res = 0while x != fa[x]:res += w[x]x = fa[x]res += w[x] # 加上根节点的贡献return resfor _ in range(q):line = list(map(int, input().split()))op = line[0]if op == 1:x, y = line[1], line[2]x = find(x)y = find(y)if x == y:continue# 按秩合并,保证 x 是较小的集合if sz[x] > sz[y]:x, y = y, xfa[x] = ysz[y] += sz[x]w[x] -= w[y] # 插值抵消elif op == 2:x, y = line[1], line[2]v[x] += yelif op == 3:x, y = line[1], line[2]w[find(x)] += yelse: # op == 4x = line[1]ans = get(x) + v[x]print(ans)if __name__ == "__main__":main()C++并查集 #include <iostream>#include <vector>using namespace std;int find(vector<int>& p, int x) {if (p[x] != x) {p[x] = find(p, p[x]);}return p[x];}void unionSets(vector<int>& p, vector<int>& rank, int x, int y) {int rx = find(p, x);int ry = find(p, y);if (rx == ry) {return;}if (rank[rx] < rank[ry]) {p[rx] = p[ry];} else if (rank[rx] > rank[ry]) {p[ry] = p[rx];} else {p[ry] = p[rx];rank[rx] += 1;}}int main() {int n, q;cin >> n >> q;vector<int> p(n + 1);vector<int> res(n + 1, 0);vector<int> rank(n + 1, 1);for (int i = 0; i <= n; i++) {p[i] = i;}for (int _ = 0; _ < q; _++) {int z, x;cin >> z >> x;if (z == 1) {int y;cin >> y;unionSets(p, rank, x, y);}else if (z == 2) {int y;cin >> y;res[x] += y;}else if (z == 3) {int y;cin >> y;for (int c = 1; c <= n; c++) {if (find(p, x) == find(p, c)) {res[c] += y;}}}else {cout << res[x] << endl;}}return 0;} -
G-DP
P16266 [蓝桥杯 2026 省 Python B 组] 星光共鸣 - 洛谷
题目又臭又长,题意为:
给定,定义一个 01 串每个长度为 的连续 1 段都会提供的贡献。
现在求有多少个长度为 的 01 串其贡献之和(也就是题目的共鸣度)不小于 k。
DP太困难,现在还在学背包(哭),
直接贴题解代码赛时DFS def dfs1(n, k):def dfs(pos, last_is_zero, cons_len, cur_val):if cur_val >= k:return 0if pos == n:return 1 if cur_val < k else 0res = dfs(pos + 1, False, 0, cur_val)new_len = cons_len + 1 if last_is_zero else 1add = new_len * (new_len + 1) // 2 - cons_len * (cons_len + 1) // 2res += dfs(pos + 1, True, new_len, cur_val + add)return resreturn dfs(0, False, 0, 0)n,k = map(int,input().split())print((1 << n) - dfs1(n, k))快速幂DP正解 import sysMOD = 10 ** 9 + 7def ksm(a, b, mod):"""快速幂 a^b % mod"""res = 1while b:if b & 1:res = res * a % moda = a * a % modb >>= 1return resdef main() -> None:n,k = map(int,input().split())# 特殊情况:k == 0 时直接输出 2^nif k == 0:print(ksm(2, n, MOD))return# 题目要求“共鸣值不超过 k-1”的方案数,因此将 k 减 1k -= 1# f[i][j] : 长度为 i 且共鸣值为 j 的方案数# s[i][j] : f[0..i][j] 的前缀和f = [[0] * (k + 1) for _ in range(n + 1)]s = [[0] * (k + 1) for _ in range(n + 1)]# 初始化f[0][0] = 1s[0][0] = 1# 外层遍历共鸣值 jfor j in range(k + 1):# 计算所有 i 的 f[i][j]for i in range(1, n + 1):# 枚举段尾 l,使区间 [l, i] 构成一个“全0”段l = iwhile l >= 1:length = i - l + 1 # 区间长度c = length * (length + 1) // 2 # 该区间产生的共鸣值if j < c:break# 上一个状态的位置:l-2(因为需要间隔至少一个1),且不能小于0prev_i = max(0, l - 2)f[i][j] = (f[i][j] + s[prev_i][j - c]) % MODl -= 1# 计算前缀和 s[i][j]for i in range(1, n + 1):s[i][j] = (s[i - 1][j] + f[i][j]) % MODtotal = ksm(2, n, MOD) # 所有可能的方案总数illegal = 0 # 不合法方案数(共鸣值 ≤ k-1)for j in range(k + 1):illegal = (illegal + s[n][j]) % MODans = (total - illegal) % MODprint(ans)if __name__ == "__main__":main() -
H-单调栈+贡献法+二阶前缀和+区间最值
赛时直接暴力,写的最舒服的暴力,完全用不到脑子
(应该是坏掉了)题意:
给定长度为 n 的整数序列 。
定义函数为整数 的十进制表示位数。
需要计算所有子区间 的总贡献和:
最终答案对 998244353 取模输出。
直接贴题解吧,比较复杂,类似牛客周赛137的E,但更加复杂,数据范围太大
赛时暴力 MOD = 998244353def digit_len(x: int) -> int:return len(str(x))def main():n = int(input())a = [0] + list(map(int,input().split()))ans = 0for l in range(1, n + 1):cur_max = 0for r in range(l, n + 1):cur_max = max(cur_max, a[r])length = r - l + 1val = digit_len(length) * cur_maxans = (ans + val) % MODprint(ans)if __name__ == "__main__":main()正解 import sysMOD = 998244353def get_f(x: int) -> int:if x < 10:return 1if x < 100:return 2if x < 1000:return 3if x < 10000:return 4if x < 100000:return 5return 6def main():data = sys.stdin.buffer.read().split()if not data:returnit = iter(data)n = int(next(it))a = [0] * (n + 1)for i in range(1, n + 1):a[i] = int(next(it))f = [0] * (n + 1)for i in range(1, n + 1):f[i] = get_f(i)L = [0] * (n + 2)st = []for i in range(1, n + 1):while st and a[st[-1]] < a[i]:st.pop()L[i] = st[-1] if st else 0st.append(i)R = [0] * (n + 2)st.clear()for i in range(n, 0, -1):while st and a[st[-1]] <= a[i]:st.pop()R[i] = st[-1] if st else n + 1st.append(i)# 前缀和 s1[i] = sum_{j=1..i} f[j], s2[i] = sum_{j=1..i} s1[j]s1 = [0] * (n + 1)s2 = [0] * (n + 1)for i in range(1, n + 1):s1[i] = (s1[i-1] + f[i]) % MODs2[i] = (s2[i-1] + s1[i]) % MODans = 0for i in range(1, n + 1):lc = i - L[i]rc = R[i] - iif lc > rc:lc, rc = rc, lc# sum = s2[lc+rc-1] - s2[rc-1] - s2[lc-1] + 2*MODtotal = (s2[lc + rc - 1] - s2[rc - 1] - s2[lc - 1]) % MODans = (ans + (a[i] % MOD) * total) % MODprint(ans)if __name__ == "__main__":main()
写在最后
暴力场次全省116/1.4W+(其他人在干什么??)
评价是水爆了,吐槽鼠科的电脑太烂了,还有各种bug,体验很差,希望国赛在南京的学校能整的好一点(bushi)
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!