2026蓝桥省pyb补题及吐槽

2937 字
15 分钟
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=0
    x=''
    for i in range(1,2027):
    x+=str(i)
    x=int(x)
    if x%26==0:
    cnt+=1
    x=str(x)
    print(cnt)
  • B-数学

    P16261 [蓝桥杯 2026 省 Python/Java B 组] 干涉条纹 - 洛谷

    特有的B题考数学思维…(我的数学思维呢???)

    题意:

    有两个区间 [0,A],[0,B]  [0,A],[0,B] 各选一个整数 a,b  a,b 出来后,要使得 a+ba+b 是一个完全平方数,求方案数。

    其中 A=20269876543210,B=20260123456789 A=20269876543210,B=20260123456789

    题解:

    显然暴力是不可做的,区间太大了

    换个角度,通过枚举比较少的完全平方数,从0枚举到A+B,

    问题转换为:给定完全平方数S,在两个区间中各选择一个数子,加起来等于等于S有对少种选法。由于S固定,a固定后,b也固定,求a的选法即可。

    a+b=k2a + b = k^2 s=k2s = k^2 a=sba = s - b

    0bB0≤b≤B0aA0≤a≤A ,有:

    sBas0s - B ≤ a ≤ s - 0 max(0,sB)amin(s,A)max(0,s−B)≤a≤min(s,A) 合法对数=min(s,A)max(sB,0)+1合法对数 = min(s,A) - max(s - B,0) + 1
    数学
    MOD = 998244353
    ans = 0
    A = 20269876543210
    B = 20260123456789
    i = 0
    while i * i <= A + B:
    s = i * i
    l = max(0,s - B)
    r = min(s,A)
    ans += max(0,r - l + 1)
    ans %= MOD
    i += 1
    print(ans)
  • C-合数

    P16262 [蓝桥杯 2026 省 Python B 组] 定制展示盘 - 洛谷

    赛时两个for真的丑完了…

    总槽位数量要大于 n 且行数不能等于1,也就是说这个最小数,一定会被大于或等于 2 的数整除,这时我们就会发现,这个最小数一定不是质数,所以我们要求的是不小于 n 且不是质数的最小数,亦即找到一个不小于n的合数。

    1.由于x,yx,y都不小于2,答案不小于4

    2.如果nn本身是不小于4的偶数,则nn本身就是答案

    3.nn是一个不小于4的奇数,则n+1n+1一定可以

    4.答案不会超过n+1n+1,但n+1n+1不一定是答案,列如9=339 = 3*3

    5.从2开始枚举到n\sqrt{n},验证n能否写出xyx*y

    数学
    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:
    continue
    ans = n
    break
    ans = 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]*n
    for 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] += y
    elif z == 3:
    y = a[2]
    res[x-1] += y
    for c in t[x-1]:
    res[c] += y
    else:
    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:
    return
    if rank[rx] < rank[ry]:
    p[rx] = p[ry]
    elif rank[rx] > rank[ry]:
    p[ry] = p[rx]
    else:
    p[ry] = p[rx]
    rank[rx] += 1
    def 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] += y
    elif z == 3:
    y = a[2]
    for c in range(1,n+1):
    if find(p,x) == find(p,c):
    res[c] += y
    else:
    print(res[x])
    if __name__ == "__main__":
    main()
    按秩合并
    import sys
    def main():
    input = sys.stdin.readline
    n, 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 x
    def get(x):
    # 获取节点 x 所在集合的根节点的 w 累加值
    res = 0
    while x != fa[x]:
    res += w[x]
    x = fa[x]
    res += w[x] # 加上根节点的贡献
    return res
    for _ 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, x
    fa[x] = y
    sz[y] += sz[x]
    w[x] -= w[y] # 插值抵消
    elif op == 2:
    x, y = line[1], line[2]
    v[x] += y
    elif op == 3:
    x, y = line[1], line[2]
    w[find(x)] += y
    else: # op == 4
    x = 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 组] 星光共鸣 - 洛谷

    题目又臭又长,题意为:

    给定n,k n,k,定义一个 01 串每个长度为 xx 的连续 1 段都会提供x(x+1)/2x*(x+1)/2的贡献。

    现在求有多少个长度为 n 的 01 串其贡献之和(也就是题目的共鸣度)不小于 k。

    DP太困难,现在还在学背包(哭),直接贴题解代码

    赛时DFS
    def dfs1(n, k):
    def dfs(pos, last_is_zero, cons_len, cur_val):
    if cur_val >= k:
    return 0
    if pos == n:
    return 1 if cur_val < k else 0
    res = dfs(pos + 1, False, 0, cur_val)
    new_len = cons_len + 1 if last_is_zero else 1
    add = new_len * (new_len + 1) // 2 - cons_len * (cons_len + 1) // 2
    res += dfs(pos + 1, True, new_len, cur_val + add)
    return res
    return dfs(0, False, 0, 0)
    n,k = map(int,input().split())
    print((1 << n) - dfs1(n, k))
    快速幂DP正解
    import sys
    MOD = 10 ** 9 + 7
    def ksm(a, b, mod):
    """快速幂 a^b % mod"""
    res = 1
    while b:
    if b & 1:
    res = res * a % mod
    a = a * a % mod
    b >>= 1
    return res
    def main() -> None:
    n,k = map(int,input().split())
    # 特殊情况:k == 0 时直接输出 2^n
    if k == 0:
    print(ksm(2, n, MOD))
    return
    # 题目要求“共鸣值不超过 k-1”的方案数,因此将 k 减 1
    k -= 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] = 1
    s[0][0] = 1
    # 外层遍历共鸣值 j
    for j in range(k + 1):
    # 计算所有 i 的 f[i][j]
    for i in range(1, n + 1):
    # 枚举段尾 l,使区间 [l, i] 构成一个“全0”段
    l = i
    while l >= 1:
    length = i - l + 1 # 区间长度
    c = length * (length + 1) // 2 # 该区间产生的共鸣值
    if j < c:
    break
    # 上一个状态的位置:l-2(因为需要间隔至少一个1),且不能小于0
    prev_i = max(0, l - 2)
    f[i][j] = (f[i][j] + s[prev_i][j - c]) % MOD
    l -= 1
    # 计算前缀和 s[i][j]
    for i in range(1, n + 1):
    s[i][j] = (s[i - 1][j] + f[i][j]) % MOD
    total = ksm(2, n, MOD) # 所有可能的方案总数
    illegal = 0 # 不合法方案数(共鸣值 ≤ k-1)
    for j in range(k + 1):
    illegal = (illegal + s[n][j]) % MOD
    ans = (total - illegal) % MOD
    print(ans)
    if __name__ == "__main__":
    main()
  • H-单调栈+贡献法+二阶前缀和+区间最值

    赛时直接暴力,写的最舒服的暴力,完全用不到脑子 (应该是坏掉了)

    题意:

    给定长度为 n 的整数序列 a1,a2,,ana1,a2,…,an

    定义函数 f(x)  f(x) 为整数 x x 的十进制表示位数。

    需要计算所有子区间 [l,r][l,r] 的总贡献和:

    l=1nr=lnf(rl+1)×maxlirai\begin{aligned}\\\sum_{l=1}^{n}\sum_{r=l}^{n}f(r-l+1)\times\max_{l\leq i\leq r}a_i\\\end{aligned}

    最终答案对 998244353 取模输出。

    直接贴题解吧,比较复杂,类似牛客周赛137的E,但更加复杂,数据范围太大

    赛时暴力
    MOD = 998244353
    def digit_len(x: int) -> int:
    return len(str(x))
    def main():
    n = int(input())
    a = [0] + list(map(int,input().split()))
    ans = 0
    for l in range(1, n + 1):
    cur_max = 0
    for r in range(l, n + 1):
    cur_max = max(cur_max, a[r])
    length = r - l + 1
    val = digit_len(length) * cur_max
    ans = (ans + val) % MOD
    print(ans)
    if __name__ == "__main__":
    main()
    正解
    import sys
    MOD = 998244353
    def get_f(x: int) -> int:
    if x < 10:
    return 1
    if x < 100:
    return 2
    if x < 1000:
    return 3
    if x < 10000:
    return 4
    if x < 100000:
    return 5
    return 6
    def main():
    data = sys.stdin.buffer.read().split()
    if not data:
    return
    it = 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 0
    st.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 + 1
    st.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]) % MOD
    s2[i] = (s2[i-1] + s1[i]) % MOD
    ans = 0
    for i in range(1, n + 1):
    lc = i - L[i]
    rc = R[i] - i
    if lc > rc:
    lc, rc = rc, lc
    # sum = s2[lc+rc-1] - s2[rc-1] - s2[lc-1] + 2*MOD
    total = (s2[lc + rc - 1] - s2[rc - 1] - s2[lc - 1]) % MOD
    ans = (ans + (a[i] % MOD) * total) % MOD
    print(ans)
    if __name__ == "__main__":
    main()

写在最后#

暴力场次全省116/1.4W+(其他人在干什么??)

评价是水爆了,吐槽鼠科的电脑太烂了,还有各种bug,体验很差,希望国赛在南京的学校能整的好一点(bushi)

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

2026蓝桥省pyb补题及吐槽
http://blog.7a7a68.xyz/posts/2026蓝桥省pyb补题及吐槽/
作者
7a7a68
发布于
2026-04-19
许可协议
CC BY-NC-SA 4.0

评论区

Profile Image of the Author
7a7a68
愿你明日如绚丽之花.
公告
留言暂不可用
音乐
封面

音乐

暂未播放

0:00 0:00
暂无歌词
分类
标签
站点统计
文章
7
分类
4
标签
5
总字数
9,377
运行时长
0
最后活动
0 天前

目录