Codeforces 988div3 [A-G]个人题解

目录

Twice

原题链接

思路分析

AC代码

Intercepted Inputs

原题链接

思路分析

AC代码

Superultra's Favorite Permutation

原题链接

思路分析

AC代码

Sharky Surfing

原题链接

思路分析

AC代码

Kachina's Favorite Binary String

原题链接

思路分析

AC代码

Ardent Flames

原题链接

思路分析

AC代码

Natlan Exploring

原题链接

思路分析

AC代码


Twice

原题链接

Twice

思路分析

直接计数即可

时间复杂度:O(N)

AC代码

from bisect import *
import copy
import sys
from math import *
from math import inf
import heapq
from collections import Counter
from itertools import accumulate
from typing import *
import os
from types import GeneratorType


def bootstrap(f, stack=[]):
    def wrappedfunc(*args, **kwargs):
        if stack:
            return f(*args, **kwargs)
        else:
            to = f(*args, **kwargs)
            while True:
                if type(to) is GeneratorType:
                    stack.append(to)
                    to = next(to)
                else:
                    stack.pop()
                    if not stack:
                        break
                    to = stack[-1].send(to)
            return to

    return wrappedfunc

input = lambda: sys.stdin.readline().strip()
output = lambda x: sys.stdout.write(str(x) + '\n')
MII = lambda: map(int, input().split())
LMI = lambda: list(map(int, input().split()))
LI = lambda: list(input())
II = lambda: int(input())
I = lambda: input()
fmax = lambda x, y: x if x > y else y
fmin = lambda x, y: x if x < y else y

# sys.stdin = open('in.txt', 'r')

def solve():
    n = II()
    a = LMI()
    res = 0
    cnt = Counter(a)
    for x in cnt.values():
        res += x // 2
    print(res)
    pass



if __name__ == "__main__":
    T = 1
    T = II()
    for _ in range(T):
        solve()

Intercepted Inputs

原题链接

Intercepted Inputs

思路分析

找到两个数乘积为 k - 2 即可

时间复杂度:O(k)

AC代码

#include <bits/stdc++.h>

// #define DEBUG

using u32 = unsigned;
using i64 = long long;
using u64 = unsigned long long;

constexpr int inf32 = 1E9 + 7;
constexpr i64 inf64 = 1E18 + 7;

void solve() {
    int k;
    std::cin >> k;
    int n = -1, m = -1;
    std::vector<int> a(k);
    for (int i = 0; i < k; ++ i) {
        std::cin >> a[i];
    }
    k -= 2;
    std::set<int> st;
    for (int x : a) {
        if (k % x == 0 && st.contains(k / x)) {
            n = x;
            m = k / x;
            break;
        }
        st.insert(x);
    }
    assert(n != -1 && m != -1);
    std::cout << n << ' ' << m << '\n';
}

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

#ifdef DEBUG
    int START = clock();
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif
    int t = 1;
    std::cin >> t;

    while (t --) {
        solve();
    }
#ifdef DEBUG
    std::cerr << "run-time: " << clock() - START << '\n';
#endif
    return 0;
}

Superultra's Favorite Permutation

原题链接

Superultra's Favorite Permutation

思路分析

和上次div2C的构造思路类似

1~4 无法构造

从5开始,我们奇数放一边,偶数放一边,奇数相加和偶数相加都是合数,只需找到一对奇数偶数之和为合数,最小的pair 为 4 + 5 = 9

时间复杂度:O(N)

AC代码

#include <bits/stdc++.h>

// #define DEBUG

using u32 = unsigned;
using i64 = long long;
using u64 = unsigned long long;

constexpr int inf32 = 1E9 + 7;
constexpr i64 inf64 = 1E18 + 7;

void solve() {
    int n;
    std::cin >> n;

    if (n <= 4) {
        std::cout << "-1\n";
        return;
    }

    std::vector<int> p;

    for (int i = 1; i <= n; i += 2) {
        if (i == 5) {
            continue;
        }
        p.push_back(i);
    }

    p.push_back(5);
    p.push_back(4);
    // 1 2 3 4 5
    // 2 4 5 1 3

    for (int i = 2; i <= n; i += 2) {
        if (i == 4) {
            continue;
        }
        p.push_back(i);
    }

    for (int i = 0; i < n; ++ i) {
        std::cout << p[i] << " \n"[i + 1 == n];
    }    
}

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

#ifdef DEBUG
    int START = clock();
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif
    int t = 1;
    std::cin >> t;

    while (t --) {
        solve();
    }
#ifdef DEBUG
    std::cerr << "run-time: " << clock() - START << '\n';
#endif
    return 0;
}

Sharky Surfing

原题链接

Sharky Surfing

思路分析

直接堆模拟即可,就是在不得不拿的时候,拿前面能拿的当中最大的那个

时间复杂度:O(NlogN)

AC代码

#include <bits/stdc++.h>

// #define DEBUG

using u32 = unsigned;
using i64 = long long;
using u64 = unsigned long long;

constexpr int inf32 = 1E9 + 7;
constexpr i64 inf64 = 1E18 + 7;

void solve() {
    int n, m, L;
    std::cin >> n >> m >> L;

    std::vector<std::pair<int, int>> segs(n);
    for (int i = 0; i < n; ++ i) {
        int l, r;
        std::cin >> l >> r;
        segs[i] = {l, r};
    }

    std::vector<std::pair<int, i64>> p(m);
    std::map<int, i64> f;
    for (int i = 0; i < m; ++ i) {
        int x, v;
        std::cin >> x >> v;
        p[i] = {x, v};
        f[x] += v;
    }

    std::ranges::sort(p);

    std::priority_queue<i64> pq;

    int i = 0;

    i64 cur = 1;
    int ans = 0;

    for (auto &[l, r] : segs){
        while (i < p.size() && p[i].first < l) {
            pq.push(p[i].second);
            ++ i;
        }

        while (cur < r - l + 2) {
            if (pq.empty()) {
                std::cout << "-1\n";
                return;
            }
            cur += pq.top();
            pq.pop();
            ++ ans;
        }
    }

    std::cout << ans << '\n';
}

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

#ifdef DEBUG
    int START = clock();
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif
    int t = 1;
    std::cin >> t;

    while (t --) {
        solve();
    }
#ifdef DEBUG
    std::cerr << "run-time: " << clock() - START << '\n';
#endif
    return 0;
}

Kachina's Favorite Binary String

原题链接

Kachina's Favorite Binary String

思路分析

思维+构造

如果f(1, n) = 0,那么impossible

设第一个0的位置为st0,[[1, st0 - 1], n] 的值都等于 f(1, n)

我们可以找到st0

然后从st0 + 1 一直闻到 n - 1,记录上一次询问<st0, i - 1> 的值last

只要 f(st0, i) > last,那么s[i] = 1,否则为0

这样一共问了n次,但是没有问(st0, n),显然 (st0, n) = f(1, n),一开始就问过了

我们根据 last 和 f(1. n) 的关系即可求出 s[n]

刚好问了n次,比较极限(当然可以剪枝,但是最坏还是n次)

时间复杂度:O(N)

AC代码

#include <bits/stdc++.h>

// #define DEBUG

using u32 = unsigned;
using i64 = long long;
using u64 = unsigned long long;

constexpr int inf32 = 1E9 + 7;
constexpr i64 inf64 = 1E18 + 7;

int query(int l, int r) {
    std::cout << "? " << l << ' ' << r << std::endl;

    int res;
    std::cin >> res;

    return res;
}

void solve() {
    int n;
    std::cin >> n;

    int tot = query(1, n);
    if (tot == 0) {
        std::cout << "! IMPOSSIBLE" << std::endl;
        return;
    }

    std::string s(n, '0');

    int i = 2;
    while (i < n && query(i, n) == tot) {
        s[i - 2] = '1';
        ++ i;
    }

    s[i - 2] = '0';
    int st0 = i - 1;
    int last = 0;
    for (; i < n; ++ i) {
        int res = query(st0, i);
        if (res > last) {
            s[i - 1] = '1';
        } else {
            s[i - 1] = '0';
        }
        last = res;
    }

    if (last == tot) {
        s[n - 1] = '0';
    } else {
        s[n - 1] = '1';
    }

    std::cout << "! " << s << std::endl;
}

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

#ifdef DEBUG
    int START = clock();
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif
    int t = 1;
    std::cin >> t;

    while (t --) {
        solve();
    }
#ifdef DEBUG
    std::cerr << "run-time: " << clock() - START << '\n';
#endif
    return 0;
}

Ardent Flames

原题链接

Ardent Flames

思路分析

二分+差分

二分次数mid

对于 <x[i], h[i]>,要在mid次被击败,则

m - |p - x| >= ceil(h[i] / mid)

得出 x - (m - ceil(h[i] / mid))  <= p <= x + m - ceil(h[i] / mid)

我们差分对 每个怪物贡献的区间+1,然后对差分做前缀和,只要某个点被覆盖了k次以上,就返回true,否则false

时间复杂度:O(N log U logN),U为值域

AC代码

#include <bits/stdc++.h>

// #define DEBUG

using u32 = unsigned;
using i64 = long long;
using u64 = unsigned long long;

constexpr int inf32 = 1E9 + 7;
constexpr i64 inf64 = 1E18 + 7;

void solve() {
    int n, m, k;
    std::cin >> n >> m >> k;

    std::vector<int> h(n), x(n);
    for (int i = 0; i < n; ++ i) {
        std::cin >> h[i];
    }
    for (int i = 0; i < n; ++ i) {
        std::cin >> x[i];
    }

    auto check = [&](int mid) -> bool {
        std::map<int, int> f;

        for (int i = 0; i < n; ++ i) {
            int val = m - (h[i] + mid - 1) / mid;
            if (val < 0) {
                continue;
            }

            ++ f[x[i] - val];
            -- f[x[i] + val + 1];
        }

        int s = 0;

        for (auto &[pos, v] : f) {
            s += v;
            if (s >= k) {
                return true;
            }
        }

        return false;
    };

    int lo = 1, hi = std::ranges::max(h);
    int ans = -1;

    while (lo <= hi) {
        int mid = (lo + hi) / 2;
        if (check(mid)) {
            ans = mid;
            hi = mid - 1;
        } else {
            lo = mid + 1;
        }
    }

    std::cout << ans << '\n';
}

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

#ifdef DEBUG
    int START = clock();
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif
    int t = 1;
    std::cin >> t;

    while (t --) {
        solve();
    }
#ifdef DEBUG
    std::cerr << "run-time: " << clock() - START << '\n';
#endif
    return 0;
}

Natlan Exploring

原题链接

Natlan Exploring

思路分析

拓扑序dp+容斥

由于我不会莫比乌斯,所以用了暴力容斥

预处理 minp[x],即 x 的最小质因子

然后预处理 facs[i],即 a[i] 的质因子集合

定义 f[i] 为 到达 i 的路径数,sum[p1 p2 ... pk] 为  到达 被 p1 p2 ... pk整除的节点的路径数

那么对于第i个节点 而言,它有 len(facs[i])个不同的质因子

直接累加 Σ sum[p1 p2 ... pk] 显然是会重复的,我们需要做容斥(容斥原理自行搜索)

即:f[i] += Σ sum[p1 p2 ... pk] * sign,sgn = (-1)^{k + 1}

然后对于 sum[p1 p2 ... pk] 累加 f[i] 即可

时间复杂度:O(NlnM + 2^ln(M) * n * ln(M))

AC代码

#include <bits/stdc++.h>

// #define DEBUG

using u32 = unsigned;
using i64 = long long;
using u64 = unsigned long long;

constexpr int inf32 = 1E9 + 7;
constexpr i64 inf64 = 1E18 + 7;

template<class T>
constexpr T power(T a, i64 b) {
    T res = 1;
    for (; b; b /= 2, a *= a) {
        if (b % 2) {
            res *= a;
        }
    }
    return res;
}

constexpr i64 mul(i64 a, i64 b, i64 p) {
    i64 res = a * b - i64(1.L * a * b / p) * p;
    res %= p;
    if (res < 0) {
        res += p;
    }
    return res;
}
template<i64 P>
struct MLong {
    i64 x;
    constexpr MLong() : x{} {}
    constexpr MLong(i64 x) : x{norm(x % getMod())} {}
    
    static i64 Mod;
    constexpr static i64 getMod() {
        if (P > 0) {
            return P;
        } else {
            return Mod;
        }
    }
    constexpr static void setMod(i64 Mod_) {
        Mod = Mod_;
    }
    constexpr i64 norm(i64 x) const {
        if (x < 0) {
            x += getMod();
        }
        if (x >= getMod()) {
            x -= getMod();
        }
        return x;
    }
    constexpr i64 val() const {
        return x;
    }
    explicit constexpr operator i64() const {
        return x;
    }
    constexpr MLong operator-() const {
        MLong res;
        res.x = norm(getMod() - x);
        return res;
    }
    constexpr MLong inv() const {
        assert(x != 0);
        return power(*this, getMod() - 2);
    }
    constexpr MLong &operator*=(MLong rhs) & {
        x = mul(x, rhs.x, getMod());
        return *this;
    }
    constexpr MLong &operator+=(MLong rhs) & {
        x = norm(x + rhs.x);
        return *this;
    }
    constexpr MLong &operator-=(MLong rhs) & {
        x = norm(x - rhs.x);
        return *this;
    }
    constexpr MLong &operator/=(MLong rhs) & {
        return *this *= rhs.inv();
    }
    friend constexpr MLong operator*(MLong lhs, MLong rhs) {
        MLong res = lhs;
        res *= rhs;
        return res;
    }
    friend constexpr MLong operator+(MLong lhs, MLong rhs) {
        MLong res = lhs;
        res += rhs;
        return res;
    }
    friend constexpr MLong operator-(MLong lhs, MLong rhs) {
        MLong res = lhs;
        res -= rhs;
        return res;
    }
    friend constexpr MLong operator/(MLong lhs, MLong rhs) {
        MLong res = lhs;
        res /= rhs;
        return res;
    }
    friend constexpr std::istream &operator>>(std::istream &is, MLong &a) {
        i64 v;
        is >> v;
        a = MLong(v);
        return is;
    }
    friend constexpr std::ostream &operator<<(std::ostream &os, const MLong &a) {
        return os << a.val();
    }
    friend constexpr bool operator==(MLong lhs, MLong rhs) {
        return lhs.val() == rhs.val();
    }
    friend constexpr bool operator!=(MLong lhs, MLong rhs) {
        return lhs.val() != rhs.val();
    }
};

template<>
i64 MLong<0LL>::Mod = i64(1E18) + 9;

template<int P>
struct MInt {
    int x;
    constexpr MInt() : x{} {}
    constexpr MInt(i64 x) : x{norm(x % getMod())} {}
    
    static int Mod;
    constexpr static int getMod() {
        if (P > 0) {
            return P;
        } else {
            return Mod;
        }
    }
    constexpr static void setMod(int Mod_) {
        Mod = Mod_;
    }
    constexpr int norm(int x) const {
        if (x < 0) {
            x += getMod();
        }
        if (x >= getMod()) {
            x -= getMod();
        }
        return x;
    }
    constexpr int val() const {
        return x;
    }
    explicit constexpr operator int() const {
        return x;
    }
    constexpr MInt operator-() const {
        MInt res;
        res.x = norm(getMod() - x);
        return res;
    }
    constexpr MInt inv() const {
        assert(x != 0);
        return power(*this, getMod() - 2);
    }
    constexpr MInt &operator*=(MInt rhs) & {
        x = 1LL * x * rhs.x % getMod();
        return *this;
    }
    constexpr MInt &operator+=(MInt rhs) & {
        x = norm(x + rhs.x);
        return *this;
    }
    constexpr MInt &operator-=(MInt rhs) & {
        x = norm(x - rhs.x);
        return *this;
    }
    constexpr MInt &operator/=(MInt rhs) & {
        return *this *= rhs.inv();
    }
    friend constexpr MInt operator*(MInt lhs, MInt rhs) {
        MInt res = lhs;
        res *= rhs;
        return res;
    }
    friend constexpr MInt operator+(MInt lhs, MInt rhs) {
        MInt res = lhs;
        res += rhs;
        return res;
    }
    friend constexpr MInt operator-(MInt lhs, MInt rhs) {
        MInt res = lhs;
        res -= rhs;
        return res;
    }
    friend constexpr MInt operator/(MInt lhs, MInt rhs) {
        MInt res = lhs;
        res /= rhs;
        return res;
    }
    friend constexpr std::istream &operator>>(std::istream &is, MInt &a) {
        i64 v;
        is >> v;
        a = MInt(v);
        return is;
    }
    friend constexpr std::ostream &operator<<(std::ostream &os, const MInt &a) {
        return os << a.val();
    }
    friend constexpr bool operator==(MInt lhs, MInt rhs) {
        return lhs.val() == rhs.val();
    }
    friend constexpr bool operator!=(MInt lhs, MInt rhs) {
        return lhs.val() != rhs.val();
    }
};

template<>
int MInt<0>::Mod = 998244353;

template<int V, int P>
constexpr MInt<P> CInv = MInt<P>(V).inv();

constexpr int P = 998244353;
using Z = MInt<P>;

std::vector<int> minp, primes;
void sieve(int n) {
    minp.assign(n + 1, -1);
    primes.clear();

    for (int i = 2; i <= n; ++ i) {
        if (minp[i] == -1){
            minp[i] = i;
            primes.push_back(i);
        }

        for (int j : primes) {
            if (i * j > n) break;
            minp[i * j] = j;
            if (j == minp[i]) break;
        }
    }
}

void solve() {
    int n;
    std::cin >> n;

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

    const int M = std::ranges::max(a);
    sieve(M);

    std::vector<std::vector<int>> facs(n);

    for (int i = 0; i < n; ++ i) {
        int x = a[i];
        while (x > 1) {
            facs[i].push_back(minp[x]);
            int p = minp[x];
            while (x % p == 0) {
                x /= p;
            }
        }
    }

    std::vector<Z> f(n), sum(M + 1);

    f[0] = 1;

    for (int i = 0; i < n; ++ i) {
        std::vector<int> nodes;
        for (int j = 1, ed = 1 << facs[i].size(); j < ed; ++ j) {
            int sgn = -1, p = 1;
            Z s = 0;
            for (int k = 0; k < facs[i].size(); ++ k) {
                if (j >> k & 1) {
                    sgn *= -1;
                    p *= facs[i][k];
                }
            }

            f[i] += sum[p] * sgn;
            nodes.push_back(p);
        }
        for (int v : nodes) {
            sum[v] += f[i];
        }
    }

    std::cout << f[n - 1] << '\n';    
}

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

#ifdef DEBUG
    int START = clock();
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif
    int t = 1;
    // std::cin >> t;

    while (t --) {
        solve();
    }
#ifdef DEBUG
    std::cerr << "run-time: " << clock() - START << '\n';
#endif
    return 0;
}

### Codeforces Round 1013 Div. 3 部分题目解析 #### A. Good Numbers 此题的核心在于统计输入数据中特定数字的频率并验证其是否满足条件。具体实现方法如下: 程序通过 `map` 数据结构存储每个数字出现的次数,并逐一检查这些计数值是否达到指定的要求。 ```cpp void solve() { int n, m, k; cin >> n; map<int, int> mp; vector<int> a(n + 1); for (int i = 1; i <= n; i++) { cin >> a[i]; } for (int i = 1; i <= n; i++) { mp[a[i]]++; if (mp[2] >= 2 && mp[0] >= 3 && mp[1] >= 1 && mp[3] >= 1 && mp[5] >= 1) { cout << i << endl; return; } } cout << 0 << endl; } ``` 上述代码逻辑清晰地展示了如何利用哈希表来解决该问题[^1]。 --- #### B. Team Training 对于本题,目标是从给定字符串中删除某些字符以形成子串 `"2020"`。解决方案采用枚举的方式尝试不同的分割位置组合,从而快速判断是否存在合法方案。 以下是完整的 C++ 实现代码片段: ```cpp #include <bits/stdc++.h> using namespace std; #define int long long #define endl &#39;\n&#39; void solve() { int n; string a; cin >> n >> a; for (int i = 0; i <= 4; i++) { if (a.substr(0, i) + a.substr(n - (4 - i), 4 - i) == "2020") { puts("YES"); return; } } puts("NO"); } signed main() { int _ = 1; cin >> _; while (_--) solve(); } ``` 这段代码实现了对所有可能情况的有效覆盖,并提供了高效的解答方式。 --- #### 更多题目概述 虽然未提供其他题目的详细描述,但可以根据比赛惯例推测其余部分涉及的内容范围广泛,涵盖了动态规划、贪心算法以及图论等领域知识点。有兴趣者可访问官方平台获取完整版题解资料[^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_Equinox

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值