2026年码蹄杯 本科院校赛道&青少年挑战赛道提高组初赛(省赛)第一场,个人题解

文章目录

    • 零、写在前面
    • [一、MC0547 子胥渡江计数](#一、MC0547 子胥渡江计数)
      • [1.1 原题链接](#1.1 原题链接)
      • [1.2 思路分析](#1.2 思路分析)
      • [1.3 AC代码](#1.3 AC代码)
    • [二、MC0548 公子密会子胥](#二、MC0548 公子密会子胥)
      • [2.1 原题链接](#2.1 原题链接)
      • [2.2 思路分析](#2.2 思路分析)
      • [2.3 AC代码](#2.3 AC代码)
    • [三、MC0549 专诸市井被荐](#三、MC0549 专诸市井被荐)
      • [3.1 原题链接](#3.1 原题链接)
      • [3.2 思路分析](#3.2 思路分析)
      • [3.3 AC代码](#3.3 AC代码)
    • [四、MC0550 鱼肠剑试锋芒](#四、MC0550 鱼肠剑试锋芒)
      • [4.1 原题链接](#4.1 原题链接)
      • [4.2 思路分析](#4.2 思路分析)
      • [4.3 AC代码](#4.3 AC代码)
    • [五、MC0551 炙鱼术隐杀机](#五、MC0551 炙鱼术隐杀机)
      • [5.1 原题链接](#5.1 原题链接)
      • [5.2 思路分析](#5.2 思路分析)
      • [5.3 AC代码](#5.3 AC代码)
    • [六、MC0552 伏兵暗室设宴](#六、MC0552 伏兵暗室设宴)
      • [6.1 原题链接](#6.1 原题链接)
      • [6.2 思路分析](#6.2 思路分析)
      • [6.3 AC代码](#6.3 AC代码)
    • [七、MC0553 鱼腹剑刺王僚](#七、MC0553 鱼腹剑刺王僚)
      • [7.1 原题链接](#7.1 原题链接)
      • [7.2 思路分析](#7.2 思路分析)
      • [7.3 AC代码](#7.3 AC代码)
    • [八、MC0554 阖闾立吴赏功](#八、MC0554 阖闾立吴赏功)
      • [8.1 原题链接](#8.1 原题链接)
      • [8.2 思路分析](#8.2 思路分析)
      • [8.3 AC代码](#8.3 AC代码)
    • [九、MC0555 子胥谋楚伐兵](#九、MC0555 子胥谋楚伐兵)
      • [9.1 原题链接](#9.1 原题链接)
      • [9.2 思路分析](#9.2 思路分析)
      • [9.3 AC代码](#9.3 AC代码)
    • [十、MC0556 掘墓统计铭文](#十、MC0556 掘墓统计铭文)
      • [10.1 原题链接](#10.1 原题链接)
      • [10.2 思路分析](#10.2 思路分析)
      • [10.3 AC代码](#10.3 AC代码)

零、写在前面

毕竟是省赛,基本都是经典算法题,拿来练手还是不错的。

题解写的比较简略。

一、MC0547 子胥渡江计数

1.1 原题链接

MC0547 子胥渡江计数

1.2 思路分析

签到

1.3 AC代码

python 复制代码
n = int(input())
f = g = 0
for i in range(n):
    a, b = map(int, input().split())
    if b >= a: f += 1
    else: g += 1
print(f, g)

二、MC0548 公子密会子胥

2.1 原题链接

MC0548公子密会子胥

2.2 思路分析

签到

2.3 AC代码

cpp 复制代码
#include <bits/stdc++.h>
using i64 = long long;
using u32 = unsigned;
using u64 = unsigned long long;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n;
    std::cin >> n;
    int min = 1E9;
    for (int i = 0; i < n; ++i) {
        int x;
        std::cin >> x;
        min = std::min(min, x); 
        std::cout << min << " \n"[i == n - 1];  
    }

    return 0;
}

三、MC0549 专诸市井被荐

3.1 原题链接

MC0549专诸市井被荐

3.2 思路分析

签到

3.3 AC代码

cpp 复制代码
#include <bits/stdc++.h>
using i64 = long long;
using u32 = unsigned;
using u64 = unsigned long long;

constexpr int P = 10007;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n, m;
    std::cin >> n >> m;
    std::vector<int> a(n);
    for (int i = 0; i < n; ++i) {
        std::cin >> a[i];
    }
    std::sort(a.begin(), a.end());
    int L = a[0], R = a[n - 1];
    int ans = 0;
    for (; m > 0; --m) {
        int l, r;
        std::cin >> l >> r;
        ans += std::max(0, std::min(n, R - r)) + std::max(0, std::min(n, l - L));
        ans %= P;
    }
    std::cout << ans << "\n";

    return 0;
}

四、MC0550 鱼肠剑试锋芒

4.1 原题链接

MC0550鱼肠剑试锋芒

4.2 思路分析

除以1我们不管

然后剩下的最多除log次就变0了,数组全为0就不用操作了

4.3 AC代码

cpp 复制代码
#include <bits/stdc++.h>
using i64 = long long;
using u32 = unsigned;
using u64 = unsigned long long;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n, q;
    std::cin >> n >> q;
    std::vector<int> a(n);  
    int ans = 0;
    for (int i = 0; i < n; ++i) {
        std::cin >> a[i];
        ans += a[i];
    }
    bool ok = true;
    for (; q > 0; --q) {
        int x;
        std::cin >> x;
        if (x > 1 && ok) {
            ok = false;
            for (int &y : a) {
                ans -= y;
                y /= x;
                ans += y;
                if (y > 0) {
                    ok = true;
                }
            }
        }
        std::cout << ans << '\n';
    }

    return 0;
}

五、MC0551 炙鱼术隐杀机

5.1 原题链接

MC0551炙鱼术隐杀机

5.2 思路分析

题意就是给一个卷积核,在一个矩阵上做异或的卷积运算

似乎很难优化,但想一想深度学习中那种Hadamard乘积都没法突破复杂度,这个如果能做肯定是从异或运算本身考虑

卷积核中每个数都会扫过原矩阵中的一个矩形区域

如果卷积核和矩阵都是01构成的,那么对于卷积核中的一个0,只需要看他扫的矩形区域里面有多少1,反之亦然

那么我们按位考虑,每次对矩阵处理前缀和,来快速查找区域里面1的个数

5.3 AC代码

cpp 复制代码
#include <bits/stdc++.h>
using i64 = long long;
using u32 = unsigned;
using u64 = unsigned long long;

constexpr int P = 1'000'000'007;
int add(int x, int y) {
    x += y - P;
    x += (x >> 31) & P;
    return x;
}

int mul(int x, int y) {
    return 1LL * x * y % P;
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n, m;
    std::cin >> n >> m;
    std::vector<std::vector<int>> a(n, std::vector<int>(n));
    std::vector<std::vector<int>> b(m, std::vector<int>(m));

    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            std::cin >> a[i][j];
        }
    }

    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < m; ++j) {
            std::cin >> b[i][j];
        }
    }   

    int ans = 0;
    for (int p = 0; p < 30; ++p) {
        std::vector<std::vector<int>> f(n, std::vector<int>(n));    
        auto get = [&](int i, int j) {
            if (i < 0 || j < 0 || i >= n || j >= n) {
                return 0;
            }
            return f[i][j];
        };
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                f[i][j] = add(a[i][j] >> p & 1, add(get(i - 1, j), add(get(i, j - 1), P - get(i - 1, j - 1))));
            }
        }
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < m; ++j) {
                int c1 = add(get(n - m + i, n - m + j), add(get(i - 1, j - 1), add(P - get(i - 1, n - (m - j)), P - get(n - (m - i), j - 1))));
                int c0 = (n - m + 1) * (n - m + 1) - c1;
                if (b[i][j] >> p & 1) {
                    ans = add(ans, mul(c0, 1 << p));
                } else {
                    ans = add(ans, mul(c1, 1 << p));
                }
            }
        }
    }
    std::cout << ans << '\n';

    return 0;
}

六、MC0552 伏兵暗室设宴

6.1 原题链接

MC0552伏兵暗室设宴

6.2 思路分析

货物运输问题 + 贡献法

经典问题,两个长度为n且数组和相等的数组a,b,每次可以将a[i] +1, a[i + 1]-1 或者

a[i]- 1,a[i + 1]+1,问多少次操作可以使得两个数组相等

答案为 Σ|sa[i]- sb[i],其中sa和sb分别为a和b的前缀和数组

对于本题,我们只需考虑 sa[i]- sb[i] 会在多少个(s,t)中出现然后计算其贡献即可

这个不难用组合数学计算出前i个位置放j个1的字符串t的数目

6.3 AC代码

cpp 复制代码
#include <bits/stdc++.h>
using i64 = long long;
using u32 = unsigned;
using u64 = unsigned long long;

constexpr int P = 1E9 + 7;
int add(int x, int y) {
    x += y - P;
    x += (x >> 31) & P;
    return x;
}
int mul(int x, int y) {
    return 1LL * x * y % P;
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n;
    std::cin >> n;

    std::vector<std::vector<int>> binom(n + 1, std::vector<int>(n + 1));
    for (int i = 0; i <= n; ++i) {
        binom[i][0] = 1;
        for (int j = 1; j <= i; ++j) {
            binom[i][j] = add(binom[i - 1][j - 1], binom[i - 1][j]);
        }
    }

    std::string s;
    std::cin >> s;
    std::vector<int> cnt(n);
    for (int i = 0; i < n; ++i) {
        cnt[i] = s[i] - '0';
        if (i > 0) {
            cnt[i] += cnt[i - 1];
        }
    }
    int ans = 0;
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j <= std::min(cnt[n - 1], i + 1); ++j) {
            int l = j, r = cnt[n - 1] - j;
            if (l > i + 1 || r > n - i - 1) {
                continue;
            }
            ans = add(ans, mul(std::abs(cnt[i] - j), mul(binom[i + 1][l], binom[n - i - 1][r])));
        }
    }
    std::cout << ans << '\n';

    return 0;
}

七、MC0553 鱼腹剑刺王僚

7.1 原题链接

MC0553鱼腹剑刺王僚

7.2 思路分析

经典贪心

因为m不会很大,我们直接排序,堆模拟三元组,每次取出最小那个,然后扩展。

堆模拟的过程中,限制

(ij, k) => (i j, k + 1)

(i,j, 0) => (ij+ 1,0)

(i,0, 0)=> (i+ 1,0, 0)

可保证不重不漏,省去哈希表/平衡树的额外开销

7.3 AC代码

cpp 复制代码
#include <bits/stdc++.h>
using i64 = long long;
using u32 = unsigned;
using u64 = unsigned long long;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int T;
    std::cin >> T;
    while (T-- > 0) {
        int n, m;
        std::cin >> n >> m;
        std::vector<int> a(n), b(n), c(n);
        for (int i = 0; i < n; i++) {
            std::cin >> a[i];
        }
        for (int i = 0; i < n; i++) {
            std::cin >> b[i];
        }
        for (int i = 0; i < n; i++) {
            std::cin >> c[i];
        }
        std::sort(a.begin(), a.end());
        std::sort(b.begin(), b.end());
        std::sort(c.begin(), c.end());
        std::priority_queue<std::array<i64, 4>, std::vector<std::array<i64, 4>>, std::greater<>> h;
        h.push({1LL * a[0] * b[0] * c[0], 0, 0, 0});
        for (; m > 0; --m) {
            auto [x, i, j, k] = h.top();
            h.pop();
            if (j + k == 0 && i + 1 < n) {
                h.push({1LL * a[i + 1] * b[j] * c[k], i + 1, j, k});
            }
            if (k == 0 && j + 1 < n) {
                h.push({1LL * a[i] * b[j + 1] * c[k], i, j + 1, k});
            }
            if (k + 1 < n) {
                h.push({1LL * a[i] * b[j] * c[k + 1], i, j, k + 1});
            }
            std::cout << x << " \n"[m == 1];
        }
    }

    return 0;
}

八、MC0554 阖闾立吴赏功

8.1 原题链接

MC0554阖闾立吴赏功

8.2 思路分析

ODT 维护颜色段

将初始连续段插入map,对于推方块操作,以从x往右推L为例,如果操作过程中有碰到方

块,那么我们可以删除掉操作过程中所有触碰到的颜色段,然后在x+L处插入合并后的线段

操作过程中如何维护颜色段合并?

初始线段长度c=0,右端点为r=x+L+c,,然后从左到右依次遍历map中左端点不小于r的颜色段,累加颜色段长度到c
复杂度分析: 瓶颈在于我们操作过程中遍历到的颜色段数目,由于每次操作前会split,最多

增加1个线段,合并过程中颜色段数目不增,那么我们遍历的颜色段为 O(n + m) 量级,总体复杂度为 O((n + m) logn)

8.3 AC代码

cpp 复制代码
#include <bits/stdc++.h>
using i64 = long long;
using u32 = unsigned;
using u64 = unsigned long long;

constexpr i64 inf = 5E9;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n, m;
    std::cin >> n >> m;
    std::map<i64, int> f;
    std::vector<int> x(n);
    for (int i = 0; i < n; ++i) {
        std::cin >> x[i];
    }
    std::sort(x.begin(), x.end());
    
    for (int i = 0, j = 0; i < n; ) {
        j = i + 1;
        while (j < n && x[j] == x[j - 1] + 1) {
            ++j;
        }
        f[x[i]] = j - i;
        i = j;
    }
    
    f[-inf] = f[inf] = 0; 
    
    auto split = [&](i64 x) -> void {
        auto it = std::prev(f.upper_bound(x));
        if (it->first != x) {
            i64 r = it->first + it->second;
            if (r > x) {
                it->second = x - it->first;
                f[x] = r - x;
            }
        }
    };

    for (; m > 0; --m) {
        int op, L;
        i64 x;
        std::cin >> op >> x >> L;
        
        if (op == 1) {
            split(x);
            i64 r = x + L;
            int c = 0;
            for (auto it = f.lower_bound(x); it->first <= r + c; ) {
                c += it->second;
                it = f.erase(it);    
            }
            if (c > 0) {
                f[r] = c;
            }
        } else {
            split(x); 
            i64 l = x - L;
            int c = 0;
            for (auto it = std::prev(f.lower_bound(x)); it->first + it->second >= l - c; ) {
                c += it->second;
                it = f.erase(it);  
                --it;
            }
            if (c > 0) {
                f[l - c] = c;
            }
        }
    }
    
    f.erase(inf);
    f.erase(-inf);
    std::vector<i64> p;
    for (auto &[x, c] : f) {
        for (int i = 0; i < c; ++i) {
            p.push_back(x + i); 
        } 
    }
    
    assert(p.size() == n);
    for (int i = 0; i < n; ++i) {
        std::cout << p[i] << " \n"[i + 1 == n];
    }

    return 0;
}

九、MC0555 子胥谋楚伐兵

9.1 原题链接

MC0555子胥谋楚伐兵

9.2 思路分析

meet in middle + 预处理 + 01Trie + 双指针

注意n = 22时,带距离限制的子集数不会很大,我们考虑递推预处理左右两半的子集异或

和,然后双指针枚举右 +维护左,字典树维护当前插入的左半异或和,然后就是01Trie经典问题:给定x,有多少个数和x的异或值不大于y

9.3 AC代码

cpp 复制代码
#include <bits/stdc++.h>
using i64 = long long;
using u32 = unsigned;
using u64 = unsigned long long;

constexpr int N = 1 << 24;
constexpr int B = 30;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n, d, w;
    std::cin >> n >> d >> w;
    int m = n - n / 2;
    n -= m;
    std::vector<int> a(n), b(m);
    for (int i = 0; i < n; ++i) {
        std::cin >> a[i];
    }
    for (int i = 0; i < m; ++i) {
        std::cin >> b[i];
    }

    std::vector<std::array<int, 2>> ch(N);
    std::vector<int> cnt(N);
    int tot = 1;
    auto add = [&](int x) {
        int p = 1;
        for (int b = B - 1; b >= 0; --b) {
            int c = x >> b & 1;
            if (!ch[p][c]) {
                ch[p][c] = ++tot;
            }
            p = ch[p][c];
            ++cnt[p];
        }
    };
    
    i64 ans = 0;
    std::vector<std::vector<int>> f(n), g(m);
    for (int i = 0; i < n; ++i) {
        f[i].push_back(a[i]);
        if (a[i] <= w) {
            ++ans;
        }
        for (int j = 0; j <= i - d; ++j) {
            for (int x : f[j]) {
                f[i].push_back(x ^ a[i]);
                if (f[i].back() <= w) {
                    ++ans;
                }
            }
        }
    }
    for (int i = m - 1; i >= 0; --i) {
        g[i].push_back(b[i]);
        if (b[i] <= w) {
            ++ans;
        }   
        for (int j = i + d; j < m; ++j) {
            for (int x : g[j]) {
                g[i].push_back(x ^ b[i]);
                if (g[i].back() <= w) {
                    ++ans;
                }
            }
        }
    }    
    for (int i = 0, j = 0; i < m; ++i) {
        while (j < n && n + i >= j + d) {
            for (int x : f[j]) {
                add(x);
            }
            ++j;
        }
        for (int x : g[i]) {
            int p = 1;
            for (int b = B - 1; b >= 0; --b) {
                if (w >> b & 1) {
                    ans += cnt[ch[p][x >> b & 1]];
                    p = ch[p][x >> b & 1 ^ 1];
                } else {
                    p = ch[p][x >> b & 1];
                }
                if (p == 0) {
                    break;
                }
            }
            ans += cnt[p];
        }
    }
    std::cout << ans << "\n";

    return 0;
}

十、MC0556 掘墓统计铭文

10.1 原题链接

MC0556掘墓统计铭文

10.2 思路分析

签到

10.3 AC代码

cpp 复制代码
#include <bits/stdc++.h>
using i64 = long long;
using u32 = unsigned;
using u64 = unsigned long long;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    std::string s;
    std::cin >> s;
    i64 ans = 0;
    for (auto c : s) {
        ans += c;
    }
    std::cout << ans << '\n';

    return 0;
}
相关推荐
萝卜小白2 小时前
算法实习Day04-MinerU2.5-pro
人工智能·算法·机器学习
Liangwei Lin2 小时前
洛谷 P3133 [USACO16JAN] Radio Contact G
数据结构·算法
weixin_513449962 小时前
PCA、SVD 、 ICP 、kd-tree算法的简单整理总结
c++·人工智能·学习·算法·机器人
code_pgf2 小时前
Qwen2.5-VL 算法解析
人工智能·深度学习·算法·transformer
Code-keys3 小时前
Android Codec2 Filter 算法模块开发指南
android·算法·音视频·视频编解码
无忧智库3 小时前
低空经济新基建:构建低空飞行大数据中心与行业应用算法工厂的全景式蓝图(WORD)
算法
闻缺陷则喜何志丹4 小时前
【背包 组合】P7552 [COCI 2020/2021 #6] Anagramistica|普及+
c++·算法·背包·洛谷·组合
小章UPUP5 小时前
2026年第十六届MathorCup数学应用挑战赛D题国奖思路
算法
hssfscv5 小时前
软件设计师下午试题四——C语言(N皇后问题、分治、动态规划)
c语言·算法·动态规划