2024河南CCPC总结

前言:

大二,第二次打ccpc线下赛,和队友A5题,罚时太多、邀请赛铜牌和省赛铜牌。因为小失误很多,KL两题没开出来,没有发挥出队伍应有的实力。

题目链接: Dashboard - 2024 National Invitational of CCPC (Zhengzhou), 2024 CCPC Henan Provincial Collegiate Programming Contest - Codeforces

 Problem F. 优秀字符串(签到)

我和队友分别从后往前、从前往后看题。看出来M是个二分,准备写M,看榜发现F过的很多。看F,发现是个签到,就先开F.

签到题,没啥说的,模拟一下

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
#define int long long
const int N = 1e5 + 10, mod = 1e9 + 7;
int ans;
void solve()
{
    string s;
    cin >> s;
    set<char> q;
    for (int i = 0; i < min((int)s.size(), 4LL); i++)
    {
        q.insert(s[i]);
    }
    if (s.size() == 5 && s[2] == s[4] && q.size() == 4)
        ans++;
}

signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    int t;
    cin >> t;
    while (t--)
        solve();
    cout << ans << "\n";
    return 0;
}

Problem B. 扫雷 1(贪心)

看的时候以为是个dp,发现不对,直接贪心就能过。
可以统计一下,每个数出现的最后位置的下标。然后从小到大开始选择,同时修改now即可,表示now以及之前的钱都用来买这个位置的装置。now==n结束

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
#define int long long
const int N = 1e5 + 10, mod = 1e9 + 7;
void solve()
{
    int n;
    cin >> n;
    map<int, int> mp;
    for (int i = 1; i <= n; i++)
    {
        int x;
        cin >> x;
        mp[x] = i;
    }
    int ans = 0;
    int now = 0;
    int money = 0;
    for (auto [w, idx] : mp)
    {
        money += (idx - now);
        if (money >= w)
        {
            ans += money / w;
            money %= w;
        }
        now = idx;
        if (now == n)
            break;
    }
    cout << ans << "\n";
}

signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    int t;
    t = 1;
    while (t--)
        solve();
    return 0;
}

 Problem M. 有效算法(二分)

一眼二分,因为k越大,每个ai能变化的范围就越大,有单调性,判断区间能不能重叠,所以直接上二分。

边界l是可以为0的,表示每个ai都不变,适用于ai相同的情况,但我们没有考虑到,猛吃了两发罚时。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
#define int long long
const int N = 1e5 + 10, mod = 1e9 + 7;
void solve()
{
    int n;
    cin >> n;
    vector<int> a(n + 1), b(n + 1);
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    for (int i = 1; i <= n; i++)
    {
        cin >> b[i];
    }
    int l = 0, r = 1e9;
    auto check = [&](int mid) -> bool
    {
        int ll = -1e18, rr = 1e18;
        for (int i = 1; i <= n; i++)
        {
            ll = max(ll, a[i] - mid * b[i]);
            rr = min(rr, a[i] + mid * b[i]);
        }
        if (ll > rr)
            return 0;
        return 1;
    };
    while (l < r)
    {
        int mid = l + r >> 1;
        if (check(mid))
        {
            r = mid;
        }
        else
            l = mid + 1;
    }
    cout << l << '\n';
}

signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    int t;
    cin >> t;
    while (t--)
        solve();
    return 0;
}

Problem J. 排列与合数(暴力)

没有找性质,看一眼数据范围,发现就5位数。可以预处理1e4~1e5之间的数,然后跑全排列,时间复杂度是O(N*5!)完全能过。

我忘记了使用next_permutation函数前需要先将字符串排序,因此再次猛吃两发罚时。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
#define int long long
const int N = 1e5 + 10, mod = 1e9 + 7;
bool st[N];
void solve()
{
    string s;
    cin >> s;
    sort(s.begin(), s.end());
    do
    {
        int now = 0;
        for (auto c : s)
        {
            now = now * 10 + c - '0';
        }
        if (now < 10000)
            continue;
        if (st[now])
        {
            cout << now << "\n";
            return;
        }
    } while (next_permutation(s.begin(), s.end()));
    cout << -1 << "\n";
}

signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    int t;
    cin >> t;
    for (int i = 10000; i <= 100000; i++)
    {
        for (int j = 2; j * j <= i; j++)
        {
            if (i % j == 0 && i / j >= 2)
            {
                st[i] = 1;
            }
        }
    }
    while (t--)
        solve();
    return 0;
}

Problem H. 随机栈

这题是两个队友开的,我这时在看k题,没有参与此题,因此放上官方题解。


赛后补题:

 Problem L. Toxel 与 PCPC II(DP)

赛时一开始考虑贪心,发现不对,后改为DP,但实现过程中因为敲错变量,导致一直跑的是O(n^{2})复杂度的dp,赛后才发现,警钟撅烂。

定义dp数组为:在第i个bug前,已经解决了j个bug所需要花费的最小值。

以此推得dp转移方程为:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
#define int long long
const int N = 2e5 + 10, mod = 1e9 + 7;
int f[N];
void solve()
{
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= m; i++)
    {
        f[i] = 1e18;
    }
    for (int i = 1; i <= m; i++)
    {
        int x;
        cin >> x;
        for (int j = i; j >= max(0ll, i - 500); j--)
        {
            f[i] = min(f[i], f[j] + (i - j) * (i - j) * (i - j) * (i - j) + x);
        }
    }
    cout << f[m] << '\n';
}

signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    int t;
    t = 1;
    while (t--)
        solve();
    return 0;
}

 Problem K. 树上问题

还在调……

 总结:

第一次参加区域赛形式的比赛,激动与紧张互存,省内队伍比去年变少了,来了很多省外的强队,比赛前3个人压力很大,比赛过程中出现很多失误,队伍发挥失常,没能拿出应有的实力。

前几题都是思维题,算法很常见,做不到1眼出题,还是要加训。

写到最后已经急了,开始红温了。导致L题的DP卡了很久也没能调出来,很可惜。团队合作是很重要的一点,找队友思维的漏洞,三个人如果自己写自己的,那只能打铁。

  • 22
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值