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';
}
浙公网安备 33010602011771号