社区讨论
求调必关,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 条回复,欢迎继续交流。
正在加载回复...