CCPC 2024 黑龙江省赛

I. This is an easy problem

题目大意

给你一个数问二进制下有多少个1

解题思路

直接转二进制统计即可

代码实现

print(bin(int(input())).count("1"))

B. String

题目大意

给一个字符串,存在三个相同字符就可以删去,问字符串最后的结果是什么

解题思路

按题意模拟即可

代码实现

#include <bits/stdc++.h>

using i64 = long long;

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

    int siz = 0;
    std::string s, ans;
    std::cin >> s;

    for (auto ch : s) {
        ans += ch;
        siz++;
        while (siz >= 3 && ans[siz - 1] == ans[siz - 2] && ans[siz - 1] == ans[siz - 3]) {
            ans.pop_back();
            ans.pop_back();
            ans.pop_back();
            siz -= 3;
        }
    }

    if (ans.empty()) {
        std::cout << "NAN\n";
    } else {
        std::cout << ans << "\n";
    }
}

K. Puzzle

题目大意

给你四个数,可以在±*中选三个符号,求能有多少种不同的结果

解题思路

只有四个数三种符号全排列暴力统计即可

代码实现

import itertools
print(len(set([eval(f'{i[0]}{j[0]}{i[1]}{j[1]}{i[2]}{j[2]}{i[3]}') for i in list(itertools.permutations(list(map(int, input().split())), 4)) for j in list(itertools.permutations("+++---***", 3))])))

J. Trade

题目大意

给你两个n*m的矩阵ab, a [ x ] [ y ] a[x][y] a[x][y]表示商品在此地的售价, b [ x ] [ y ] b[x][y] b[x][y]表示到此地的路费,一开始在(1,1)有一个商品,要求从(1,1)出发只能向右下走,到最后一行或者最后一列结束,问是否有路线满足在路线上任意一个位置出售商品,利润始终非负,利润计算公式为 a [ x t ] [ y t ] − a [ 1 ] [ 1 ] − ∑ i = 1 t b [ x i ] [ y i ] a[x_t][y_t]-a[1][1]-\sum_{i=1}^{t} b[x_i][y_i] a[xt][yt]a[1][1]i=1tb[xi][yi]

解题思路

dp计算出每一个位置的利润,再bfs搜索非负的位置判断能不能到边界

代码实现

#include <bits/stdc++.h>

using i64 = long long;

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

    int n, m;
    std::cin >> n >> m;

    std::vector<std::vector<i64>> a(n + 1, std::vector<i64>(m + 1)), b(n + 1, std::vector<i64>(m + 1, INT_MAX)), vis(n + 1, std::vector<i64>(m + 1));
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            std::cin >> a[i][j];
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            std::cin >> b[i][j];
        }
    }
    int x = a[1][1];
    b[0][1] = b[1][0] = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            b[i][j] += std::min(b[i - 1][j], b[i][j - 1]);
            a[i][j] -= b[i][j] + x;
        }
    }

    std::queue<std::array<i64, 3>> q;
    q.push({1, 1, 1});
    while (!q.empty()) {
        auto [x, y, _] = q.front();
        q.pop();
        if (x == n || y == m) {
            std::cout << "YES\n";
            return 0;
        }
        if (x + 1 <= n && a[x + 1][y] >= 0 && !vis[x + 1][y]) {
            q.push({x + 1, y, a[x + 1][y]});
            vis[x + 1][y] = 1;
        }
        if (y + 1 <= m && a[x][y + 1] >= 0 && !vis[x][y + 1]) {
            q.push({x, y + 1, a[x][y + 1]});
            vis[x][y + 1] = 1;
        }
    }

    std::cout << "NO\n";
}

D. Card Game

题目大意

两个玩家ab在玩卡牌游戏,给定双方的血量,每张攻击牌的攻击力和防御牌(可以抵挡一次任意攻击),问a能否获胜

解题思路

换血阶段显然a出攻击力高的牌,b出攻击力低的牌最优,相当于a是不需要防御的(进攻是最好的防守),并且a必须在这个阶段就取得游戏胜利(平局就是a没赢),因此可以认为对b来说防御牌是一张无限攻击力的牌,然后对a牌降序b牌升序,一直换血直到有一方战败

代码实现

#include <bits/stdc++.h>

using i64 = long long;
const i64 INF = 4e18;

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

    int tt;
    std::cin >> tt;

    while (tt--) {
        i64 n, hpa, hpb;
        std::cin >> n >> hpa >> hpb;

        std::vector<i64> A, B;
        for (int i = 0; i < n; i++) {
            int x;
            std::cin >> x;
            if (x != -1) {
                A.push_back(x);
            }
        }
        for (int i = 0; i < n; i++) {
            int x;
            std::cin >> x;
            if (x == -1) {
                B.push_back(INF);
            } else {
                B.push_back(x);
            }
        }
        std::sort(A.begin(), A.end(), std::greater<i64>());
        std::sort(B.begin(), B.end());

        int i = 0, j = 0;
        while (hpa > 0 && hpb > 0 && i < A.size() && j < B.size()) {
            hpb -= A[i];
            hpa -= B[j];
            i++;
            j++;
        }

        if (hpa > 0 && hpb <= 0) {
            std::cout << "yes\n";
        } else {
            std::cout << "no\n";
        }
    }
}

F. Photography

题目大意

给定一张n点m边的无向图,每个点都有点权,要求最大化五个联通的点权之和

解题思路

正解是先预处理每一个点最大的三个邻接点然后暴力枚举链的两端找第五个点,但是直接枚举五个点加上一些剪枝暴力dfs好像也跑的飞快

代码实现

#include <bits/stdc++.h>

using i64 = long long;

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

    i64 n, m, ans = 0;
    std::cin >> n >> m;

    std::vector<int> a(n + 1), vis(n + 1);
    for (int i = 1; i <= n; i++) {
        std::cin >> a[i];
    }

    std::vector<std::vector<int>> g(n + 1);
    for (int i = 0; i < m; i++) {
        int u, v;
        std::cin >> u >> v;
        g[u].push_back(v);
        g[v].push_back(u);
    }

    for (int i = 1; i <= n; i++) {
        std::sort(g[i].begin(), g[i].end(), [&](int x, int y) { return a[x] > a[y]; });
    }

    std::vector<i64> b(a.begin() + 1, a.end()), pre(6);
    std::sort(b.rbegin(), b.rend());
    for (int i = 1; i <= 5; i++) {
        if (i - 1 < b.size()) {
            pre[i] = pre[i - 1] + b[i - 1];
        } else {
            pre[i] = pre[i - 1];
        }
    }

    auto dfs = [&](auto &&self, int u, int fa, int cnt, i64 x) -> void {
        cnt++;
        x += a[u];
        ans = std::max(ans, x);
        if (cnt == 5 || x + pre[5 - cnt] <= ans) {
            return;
        }
        vis[u] = 1;
        for (auto v : g[u]) {
            if (v != fa && !vis[v]) {
                self(self, v, u, cnt, x);
            }
        }
        vis[u] = 0;
    };

    for (int i = 1; i <= n; i++) {
        dfs(dfs, i, -1, 0, 0);
    }

    std::cout << ans << "\n";
}
目前尚未找到关于2024年河北省CCPC的具体官方信息。然而,可以基于以往的比情况推测一些可能的内容。 ### 参准备与注意事项 通常情况下,CCPC(中国大学生程序设计竞)会在每年的秋季举行区域。参者需注意以下几点: 1. **团队协作** 每支队伍由三名队员组成,分工合作至关重要。例如,在之前的比中,有队伍因签到题失误而导致时间浪费和罚时增加[^1]。因此,合理分配题目并快速定位错误是成功的关键。 2. **算法模板储备** 动态规划(DP)、图论、字符串处理等常见算法应熟练掌握。比如动态规划的一个经典实现如下所示: ```cpp #include <bits/stdc++.h> using namespace std; int k, n, m, dp[1005][1005]; int a[1005], b[1005]; int pa[1005] = {0}, pb[1005] = {0}; queue<int> q[1005]; int main() { int ak; cin >> ak; while (ak--) { for (int i = 1; i <= n; i++) while (!q[i].empty()) q[i].pop(); scanf("%d%d%d", &k, &n, &m); memset(dp, 0, sizeof(dp)); memset(pa, 0, sizeof(pa)); memset(pb, 0, sizeof(pb)); for (int i = 1; i <= n; i++) cin >> a[i]; for (int i = 1; i <= m; i++) cin >> b[i]; for (int i = 1; i <= n; i++) { q[a[i]].push(i); if (q[a[i]].size() == k) { pa[i] = q[a[i]].front(); q[a[i]].pop(); } } for (int i = 1; i <= n; i++) while (!q[i].empty()) q[i].pop(); for (int i = 1; i <= m; i++) { q[b[i]].push(i); if (q[b[i]].size() == k) { pb[i] = q[b[i]].front(); q[b[i]].pop(); } } for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); if (a[i] == b[j] && pa[i] != 0 && pb[j] != 0) dp[i][j] = dp[pa[i] - 1][pb[j] - 1] + k; } } printf("%d\n", dp[n][m]); } return 0; } ``` 3. **模拟训练** 定期参加ACM/ICPC风格的在线比或学校内部模拟有助于提升实战能力。通过解决类似矩形面积计算等问题来增强几何算法的理解[^3]。 ### 事安排预测 虽然具体日期未公布,但根据往年惯例,建议关注以下几个方面: - 报名截止时间和方式; - 初步计划中的比地点及日程表; - 是否存在线上预选环节。 #### 提醒事项 务必留意官网公告以及教练通知,及时调整复习策略以应对可能出现的新变化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值