cf1045 div2 + 2024 ICPC Kunming

cf1045 div2 and 2024 ICPC Kunming

div2

D

QAQ 看题解才直到的做法,竟然没往直径方面去想。

ICPC Kunming

质疑队友 理解队友 相信队友的一集

H

其实是非常一眼的题,但是总是因为神秘的精度问题和实现问题导致 wa 和 t。

首先极角排序要先用 atan2 把各个点的极角算出来,再根据极角排序。算角度的话要特别注意角度为 360 的情况

struct Node {
    int x, y;
    double angle;

    void set(int _x, int _y) {
        x = _x, y = _y;
        angle = atan2(y, x);
    }
};

double get(const Node &u, const Node &v) {
    i64 cross = 1ll * u.x * v.y - 1ll * v.x * u.y;
    i64 dot = 1ll * u.x * v.x + 1ll * u.y * v.y;

    double angle = atan2(cross, dot);

    if (angle < 0) {
        angle += PI;
    }
    return angle;
}

    std::sort(p.begin(), p.end(), [&](const auto &u, const auto &v) -> bool { return u.angle < v.angle; });
    double ans = 0;
    for (int i = 0; i < n; ++i) {
        int l = i, r = (i + k) % n;
        double angle = get(p[l], p[r]);
        if (r <= l && angle < EPS) {
            angle += PI;
        }
        ans = std::max(ans, angle);
    }
    std::cout << std::fixed << std::setprecision(10) << ans << '\n';

L

鉴定为模拟题

首先容易想到的是,最大的操作次数 cnt 是固定的。

然后还要考虑一下怎么触发亡语:先考虑炸鸡触发亡语,此时必然满足存在一个 \(h_i\) 为 1;否则只能对手触发亡语,此时必然有最小的 \(h_i^{'}\) 小于等于可操作次数 cnt。为什么要先考虑炸鸡触发亡语呢,因为炸鸡触发亡语不会让操作次数减少,而对手触发亡语就需要花费操作次数。

在实现上我们维护一个 num 表示有多少单位死亡。所以若一个血量目前为 \(x\) 的单位要死亡,就必须有 \(x \leq num\),否则,若果这个单位是炸鸡的,我们暂时无法让他死亡;但是如果是对手的且目前还有足够的操作次数,就能花费操作次数来满足 \(x \leq num\),在此之后,因为一个单位的死亡会让 num 增加 1。注意了,每次不管那方的单位死亡都可能会触发新的单位死亡,这还需要模拟一下:

void solve() {
    int n = 0, m = 0;
    std::cin >> n >> m;
    init(n, m);

    // en 表示能否触发亡语
    bool en = false;
    int cnt = 0;
    std::priority_queue<int> qa, qb;
    for (int i = 0; i < n; ++i) {
        int a = 0;
        std::cin >> a;

        if (a >= 2) {
            cnt += 1;
            a -= 1;
            qa.push(-a);
        }
        else if (a == 1) {
            if (en) {
                qa.push(-a);
            }
            else {
                cnt += 1;
                en = true;
                a = 0;
            }
        }
    }
    for (int i = 0; i < m; ++i) {
        int b = 0;
        std::cin >> b;
        qb.push(-b);
    }
    if (not en) {
        auto num = qb.top();
        qb.pop();
        if (cnt + num >= 0) {
            cnt += num;
            en = true;
        }
    }

    if (not en) {
        std::cout << "No\n";
        return;
    }

    int num = 1;
    while (true) {
        // 有单位死亡的连锁反应
        while (not qa.empty() && num + qa.top() >= 0 || not qb.empty() && num + qb.top() >= 0) {
            while (not qa.empty() && num + qa.top() >= 0) {
                num += 1;
                qa.pop();
            }
            while (not qb.empty() && num + qb.top() >= 0) {
                num += 1;
                qb.pop();
            }
        }

        if (qb.empty()) {
            break;
        }
        if (num + cnt + qb.top() >= 0) {
            cnt += num + qb.top();
            qb.pop();
            num += 1;
        }
        else {
            break;
        }
    }
    std::cout << (qb.empty() ? "Yes" : "No") << '\n';
    return;
}

C

不懂啊队友队友写过了

G

“当一题向很久都想不出来就要考虑打表了”

dp 打出所有 \(a \leq 5000\)\(b \leq 5000\) 的答案,统计一下会发现,答案最多是 14,也就是进行 14 次减法就能得到最终状态。于是猜测答案的次数会被最小值限制,所以直接爆搜,但限制递归层数为 15,就没了:

int dfs(i64 n, i64 m, int d = 0) {
    if (n == 0 || m == 0) {
        return 1;
    }
    if (d > L) {
        return N;
    }
    if (n > m) {
        std::swap(n, m);
    }
    i64 g = std::__gcd(n, m);

    return std::min(dfs(n, m - g, d + 1), dfs(n - g, m, d + 1)) + 1;
}

void solve() {
    i64 n = 0;
    i64 m = 0;
    std::cin >> n >> m;

    std::cout << dfs(n, m) << '\n';
}
posted @ 2025-10-07 00:39  Young_Cloud  阅读(16)  评论(0)    收藏  举报