Link

G

从散点中求凸包,再枚举每条线,求离该线距离最远的凸包的顶点。

#include "bits/stdc++.h"

using namespace std;
using i64 = long long;
using Point = complex<i64>;

auto cross(const Point &a, const Point &b) { 
    return imag(conj(a) * b); 
}

struct Line {
    Point a, b;
    Line() = default;
    Line(const Point &a, const Point &b) : a(a), b(b) {}
};

auto onLeft(const Point &p, const Line &l) { 
    return cross(l.b - l.a, p - l.a); 
}

template <typename F> 
int extreme(const F &dir, const vector<Point> &p) {
    int N = p.size();
    const auto check = [&](const int i) {
        return onLeft(p[(i + 1) % N], Line(p[i], dir(p[i]) + p[i])) >= 0;
    };
    const auto dir0 = dir(p[0]);
    const auto check0 = check(0);
    if (!check0 && check((int) p.size() - 1)) {
        return 0;
    }
    const auto cmp = [&](const Point &v) {
        const int vi = &v - p.data();
        if (vi == 0) {
            return 1;
        }
        const auto checkv = check(vi);
        const auto t = onLeft(v, Line(p[0], dir(p[0]) + p[0]));
        if (vi == 1 && checkv == check0 && t == 0) {
            return 1;
        }
        return checkv ^ (checkv == check0 && t <= 0);
    };
    return partition_point(p.begin(), p.end(), cmp) - p.begin();
}

pair<int, int> tangent(const Line &a, const vector<Point> &p) {
    const int i = extreme([&](...) { return +(a.b - a.a); }, p);
    const int j = extreme([&](...) { return -(a.b - a.a); }, p);
    return {i, j};
}

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

    int n;
    cin >> n;
    vector<Point> a(n);
    for (int i = 0; i < n; i++) {
        int x, y;
        cin >> x >> y;
        a[i] = Point(x, y);
    }

    sort(a.begin(), a.end(), [&](auto a, auto b) {
        if (real(a) != real(b)) {
            return real(a) < real(b);
        }
        return imag(a) < imag(b);
    });

    vector<Point> p;
    for (int i = 0; i < n; i++) {
        while (p.size() > 1 && cross(p[(int) p.size() - 1] - p[(int) p.size() - 2], a[i] - p[(int) p.size() - 2]) <= 0) {
            p.pop_back();
        }
        p.push_back(a[i]);
    }
    
    int k = p.size();
    for (int i = n - 2; i >= 0; i--) {
        while (p.size() > k && cross(p[(int) p.size() - 1] - p[(int) p.size() - 2], a[i] - p[(int) p.size() - 2]) <= 0) {
            p.pop_back();
        }
        p.push_back(a[i]);
    }
    p.pop_back();

    i64 ans = 0;
    for (int i = 0; i < n; i++) {
        Line L(Point(0, 0), a[i]);
        auto &[x, y] = tangent(L, p);
        ans = max(ans, abs(cross(p[x], a[i])));
        ans = max(ans, abs(cross(p[y], a[i])));
    }
    cout << fixed << setprecision(10) << 1.0 * ans / 2.0;

    return 0;
}

I

#include "bits/stdc++.h"

using namespace std;
using i64 = long long;

template <class T>
T exgcd(T a, T b, T &x, T &y) {
    if (!b) {
        x = 1, y = 0;
        return a;
    }
    T g = exgcd(b, a % b, y, x);
    y -= a / b * x;
    return g;
}

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

    int n, p, q, k;
    cin >> n >> p >> q >> k;

    vector<int> cost(n), w(n);
    for (int i = 0; i < n; i++) {
        int pos, like, l, r;
        cin >> pos >> like >> w[i] >> l >> r;

        int res = 2E9;
        for (int k2 = 0; k2 <= k / q; k2++) {
            int C = pos + k2 * r;
            int k1, k3;
            int g = exgcd(l, like, k1, k3);
            if (C % g) {
                continue;
            }
            int a = l / g, b = like / g, x = C / g;
            k1 = (k1 * x % b + b) % b;
            res = min(res, k1 * p + k2 * q);
        }
        cost[i] = res;
    }

    vector<int> f(k + 1);
    for (int i = 0; i < n; i++) {
        for (int j = k; j >= cost[i]; j--) {
            f[j] = max(f[j], f[j - cost[i]] + w[i]);
        }
    }
    cout << f[k] << '\n';

    return 0;
}