社区讨论

求调必关,10分,前两个ac,最后一个测试点超时

P13117[GCJ 2019 #2] New Elements: Part 2参与者 1已保存回复 0

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
0 条
当前快照
1 份
快照标识符
@mkhqupnn
此快照首次捕获于
2026/01/17 11:24
上个月
此快照最后确认于
2026/01/19 20:45
上个月
查看原帖
有大佬帮忙看看能怎么卡常嘛本鞠蒻燃尽了,这是我的代码:
CPP
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
using intt = __int128;

inline int read() {
    int x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-') f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}

struct Frac {
    intt num, den;  // numerator/denominator, always reduced, den > 0
    Frac(intt a = 0, intt b = 1) : num(a), den(b) {
        if (den < 0) num = -num, den = -den;
        intt g = __gcd(num, den);
        if (g != 0) num /= g, den /= g;
        else den = 1;
    }
};

bool operator<(const Frac& a, const Frac& b) {
    if (a.den == 0 && b.den == 0) return a.num < b.num;  // both infinite
    if (a.den == 0) return false;  // a infinite, b finite
    if (b.den == 0) return true;   // a finite, b infinite
    return (intt)a.num * b.den < (intt)b.num * a.den;
}

bool operator<=(const Frac& a, const Frac& b) {
    if (a.den == 0 && b.den == 0) return a.num <= b.num;
    if (a.den == 0) return false;
    if (b.den == 0) return true;
    return (intt)a.num * b.den <= (intt)b.num * a.den;
}

bool operator>=(const Frac& a, const Frac& b) { return b <= a; }
bool operator>(const Frac& a, const Frac& b) { return b < a; }

// Stern-Brocot tree to find smallest denominator fraction in (L, R)
Frac stern_brocot(Frac L, Frac R) {
    Frac lo(0, 1), hi(1, 0);  // 0/1 and 1/0
    while (true) {
        intt x = lo.num + hi.num;
        intt y = lo.den + hi.den;
        Frac mid(x, y);
        if (mid <= L) {
            lo = mid;
        } else if (mid >= R) {
            hi = mid;
        } else {
            return mid;
        }
    }
}

// Check if there exists integer y for given x such that L < x/y < R
bool check_x(int x, Frac L, Frac R, int& y) {
    intt low, high;
    if (R.den == 0) {  // R = infinity
        low = 1;
    } else {
        // y > x / R  => y > x * R.den / R.num
        intt t = (intt)x * R.den;
        low = t / R.num + 1;  // floor division + 1
    }
    if (L.num == 0) {  // L = 0
        high = (intt)1e18;  // effectively infinity
    } else {
        // y < x / L  => y < x * L.den / L.num
        intt t = (intt)x * L.den;
        high = (t - 1) / L.num;  // ceil(t / L.num) - 1
    }
    if (low <= high) {
        y = (int)low;
        return true;
    }
    return false;
}

void solve(int case_id) {
    int n = read();
    vector<int> C(n), J(n);
    for (int i = 0; i < n; i++) {
        C[i] = read(), J[i] = read();
    }
    Frac L(0, 1), R(1, 0);  // 0 and infinity
    bool impossible = false;
    for (int i = 0; i < n - 1; i++) {
        int dc = C[i] - C[i + 1];
        int dj = J[i] - J[i + 1];
        if (dc == 0) {
            if (dj >= 0) { impossible = true; break; }
        } else if (dj == 0) {
            if (dc >= 0) { impossible = true; break; }
        } else if (dc > 0 && dj > 0) {
            impossible = true; break;
        } else if (dc < 0 && dj < 0) {
            continue;
        } else if (dc > 0 && dj < 0) {
            Frac f(-dj, dc);
            if (f < R) R = f;
        } else {  // dc < 0 && dj > 0
            Frac f(-dj, dc);
            if (f > L) L = f;
        }
    }
    if (impossible || !(L < R)) {
        printf("Case #%lld: IMPOSSIBLE\n", case_id);
        return;
    }
    // Find smallest x
    Frac best = stern_brocot(L, R);
    int ans_x = -1, ans_y = -1;
    for (int x = 1; x <= (int)best.num; x++) {
        int y;
        if (check_x(x, L, R, y)) {
            ans_x = x;
            ans_y = y;
            break;
        }
    }
    if (ans_x == -1) {
        ans_x = (int)best.num;
        ans_y = (int)best.den;
    }
    printf("Case #%lld: %lld %lld\n", case_id, ans_x, ans_y);
}

signed main() {
    int T = read();
    for (int t = 1; t <= T; t++) {
        solve(t);
    }
    return 0;
}

回复

0 条回复,欢迎继续交流。

正在加载回复...