Codeforces Round #883 (Div. 3) A-G
A
代码
#include <bits/stdc++.h> using namespace std; using ll = long long; bool solve() { int n; cin >> n; int cnt = 0; for (int i = 1;i <= n;i++) { int a, b; cin >> a >> b; if (a > b) cnt++; } cout << cnt << '\n'; return true; } int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int t = 1; cin >> t; while (t--) { if (!solve()) cout << -1 << '\n'; } return 0; }
B
代码
#include <bits/stdc++.h> using namespace std; using ll = long long; char dt[4][4]; bool solve() { for (int i = 1;i <= 3;i++) for (int j = 1;j <= 3;j++) cin >> dt[i][j]; for (int i = 1;i <= 3;i++) { if (dt[i][1] == '.') continue; bool ok = 1; for (int j = 1;j <= 3;j++) ok &= dt[i][1] == dt[i][j]; if (ok) { cout << dt[i][1] << '\n'; return true; } } for (int j = 1;j <= 3;j++) { if (dt[1][j] == '.') continue; bool ok = 1; for (int i = 1;i <= 3;i++) ok &= dt[1][j] == dt[i][j]; if (ok) { cout << dt[1][j] << '\n'; return true; } } if (dt[1][1] != '.') { bool ok = 1; for (int i = 1;i <= 3;i++) ok &= dt[1][1] == dt[i][i]; if (ok) { cout << dt[1][1] << '\n'; return true; } } if (dt[1][3] != '.') { bool ok = 1; for (int i = 1;i <= 3;i++) ok &= dt[1][3] == dt[i][3 - i + 1]; if (ok) { cout << dt[1][3] << '\n'; return true; } } return false; } int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int t = 1; cin >> t; while (t--) { if (!solve()) cout << "DRAW" << '\n'; } return 0; }
C
代码
#include <bits/stdc++.h> using namespace std; using ll = long long; pair<int, ll> res[200007]; bool solve() { int n, m, h; cin >> n >> m >> h; for (int i = 1;i <= n;i++) { priority_queue<int, vector<int>, greater<int>> pq; for (int j = 1;j <= m;j++) { int x; cin >> x; pq.push(x); } int sum = 0; int point = 0; ll penalty = 0; while (pq.size()) { int t = pq.top(); pq.pop(); if (sum + t > h) break; sum += t; point++; penalty += sum; } res[i] = { point,penalty }; } auto tar = res[1]; auto cmp = [&](pair<int, ll> a, pair<int, ll> b) {return a.first == b.first ? a.second<b.second : a.first>b.first;}; sort(res + 1, res + n + 1, cmp); int id = lower_bound(res + 1, res + n + 1, tar, cmp) - res; cout << id << '\n'; return true; } int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int t = 1; cin >> t; while (t--) { if (!solve()) cout << -1 << '\n'; } return 0; }
D
代码
#include <bits/stdc++.h> using namespace std; using ll = long long; int y[200007] = { (int)2e9 }; bool solve() { int n; double d, h; cin >> n >> d >> h; for (int i = 1;i <= n;i++) cin >> y[i]; sort(y + 1, y + n + 1, greater<int>()); double ans = 0; for (int i = 1;i <= n;i++) { double delta = min(h, 0.0 + y[i - 1] - y[i]); ans += (2 - delta / h) * d * delta / 2; } cout << fixed << setprecision(6) << ans << '\n'; return true; } int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int t = 1; cin >> t; while (t--) { if (!solve()) cout << -1 << '\n'; } return 0; }
E
题意
给定一个 ,问是否存在 ,使得 。
题解
方法一
知识点:数学,枚举。
实际上, ,因此一定有 。
因此,我们枚举 ,令 ,然后验证这一对 。若 可行,那么一定有 。
其中开根号用的是 pow
,这个函数精度很差,但是这里是没有问题的,因为上下界都离得很远。
时间复杂度
空间复杂度
方法二
知识点:数学,二分,枚举。
注意到, 不会太大,最大只可能 ,考虑枚举 。
对于一个 ,由于 是关于 单调的,我们可以二分 ,找到使得 小于等于 的最后一个 ,随后验证这个 是否是答案即可。
注意到, 也不会超过 ,这个结论能降低常数。
时间复杂度
空间复杂度
方法三
知识点:数学,二分,枚举。
对于 的情况, 不会超过 ,因此可以枚举 ,对每个 预处理出 的所有答案。
对于 的情况,和方法一一样直接二分即可。
时间复杂度
空间复杂度
代码
方法一
#include <bits/stdc++.h> using namespace std; using ll = long long; using i128 = __int128_t; i128 qpow(i128 a, ll k) { i128 ans = 1; while (k) { if (k & 1) ans *= a; k >>= 1; a *= a; } return ans; } bool solve() { ll n; cin >> n; for (int i = 2, k;(k = pow(n, 1.0 / i)) >= 2;i++) { i128 res = (1 - qpow(k, i + 1)) / (1 - k); if (res == n) { cout << "YES" << '\n'; return true; } } return false; } int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int t = 1; cin >> t; while (t--) { if (!solve()) cout << "NO" << '\n'; } return 0; }
方法二
#include <bits/stdc++.h> using namespace std; using ll = long long; const ll INF = 2e18; ll calc(int x, int s) { ll sum = 0; __int128_t mul = 1; for (int i = 0;i <= s;i++) { if (sum + mul > INF) return INF; sum += mul; mul *= x; } return sum; } bool solve() { ll n; cin >> n; for (int i = 2;i <= 60;i++) { int l = 2, r = 1e9; while (l <= r) { int mid = l + r >> 1; if (calc(mid, i) <= n) l = mid + 1; else r = mid - 1; } if (r >= 2 && calc(r, i) == n) { cout << "YES" << '\n'; return true; } } return false; } int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int t = 1; cin >> t; while (t--) { if (!solve()) cout << "NO" << '\n'; } return 0; }
方法三
#include <bits/stdc++.h> using namespace std; using ll = long long; const ll INF = 1e18; set<ll> st; void init() { for (int i = 2;i <= 1000000;i++) { ll sum = 1 + i + 1LL * i * i; while (1 + (__int128_t)sum * i <= INF) { sum = 1 + sum * i; st.insert(sum); } } } ll calc(int x) { return 1 + x + 1LL * x * x; } bool solve() { ll n; cin >> n; if (st.count(n)) { cout << "YES" << '\n'; return true; } int l = 2, r = 1e9; while (l <= r) { int mid = l + r >> 1; if (calc(mid) <= n) l = mid + 1; else r = mid - 1; } if (r >= 2 && calc(r) == n) { cout << "YES" << '\n'; return true; } return false; } int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int t = 1; cin >> t; init(); while (t--) { if (!solve()) cout << "NO" << '\n'; } return 0; }
F
题意
房间里有 个物品,每个物品的种类为 。这些物品中,有一个是模仿者伪装的。
现在可以进行一场最多 轮的实验去找出它,每一轮按顺序发生如下事件:
- 记录当前房间内的所有物品的种类。
- 可指出一个物品确定是伪装的,则试验结束。但这个操作只能执行一次,若不确定,则要做下一步操作。
- 选出一些物品移出房间(可以不选,但模仿者始终不会被移出房间)并离开房间。随后房间里的物品会被打乱,模仿者也可以转换成别的物品(即使房间里不存在的物品)。
- 进入房间,继续下一轮。模仿者可能不转变,但最多保持两轮是同一个类型的物品。
给出操作,找到模仿者。
题解
知识点:枚举。
一开始可以不移出物品,这样若模仿者发生变化,则最多两轮一定有一个类型的物品多了一个。
移出除了多出来物品的类型以外类型的所有物品。
剩下的一定是包括模仿者的同一类型的物品,再最多不超过一轮,一定会出现一个不同类型的物品,就是模仿者。
时间复杂度
空间复杂度
代码
#include <bits/stdc++.h> using namespace std; using ll = long long; int n; int a[207]; int cnt1[10], cnt2[10]; void query(const vector<int> &del) { cout << "- " << del.size() << " "; for (auto x : del) cout << x << " "; cout << endl; n -= del.size(); for (int i = 1;i <= n;i++) cin >> a[i]; } void answer(int x) { cout << "! " << x << endl; } bool solve() { for (int i = 1;i <= 9;i++) cnt1[i] = cnt2[i] = 0; cin >> n; for (int i = 1;i <= n;i++) cin >> a[i], cnt1[a[i]]++; query({}); for (int i = 1;i <= n;i++) cnt2[a[i]]++; int type = 0; for (int i = 1;i <= 9;i++) { if (cnt1[i] < cnt2[i]) { type = i; break; } } if (!type) { for (int i = 1;i <= 9;i++) cnt2[i] = 0; query({}); for (int i = 1;i <= n;i++) cnt2[a[i]]++; for (int i = 1;i <= 9;i++) { if (cnt1[i] < cnt2[i]) { type = i; break; } } } vector<int> del; for (int i = 1;i <= n;i++) if (a[i] != type) del.push_back(i); query(del); bool ok = 0; for (int i = 1;i <= n;i++) { if (a[i] != type) { answer(i); ok = 1; break; } } if (!ok) { query({}); for (int i = 1;i <= n;i++) { if (a[i] != type) { answer(i); ok = 1; break; } } } return true; } int main() { //std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int t = 1; cin >> t; while (t--) { if (!solve()) cout << -1 << '\n'; } return 0; }
G
题意
有 种症状和 个药品,症状的情况通过一个长为 的 串给出。
每种药品治疗效果是可以使特定的一些症状消失,但副作用是使得特定的症状出现。
每种药有一个疗程 ,疗程之内不允许使用其他药。
现在给出初始症状情况,问最少需要多少天才能使得症状全部消失。
题解
知识点:最短路,状压dp,拓扑序dp。
考虑状压,将症状压缩为一个整数。
随后,我们将 种症状情况看作点, 种药看作边。显然,每个点都可以有 条出边。
假设当前的症状是 ,将要使用的药品的效果是 ,副作用是 ,那么使用后的症状为 (st & ~e) | se
,这样就构建了一条边,权值为疗程时间。
问题就变成,从初始状态到 状态的最短路,直接跑最短路即可。
求最短路的本质就是在最短路图这个DAG上进行拓扑序dp,因此一些dp可以考虑抽象成图的形式跑最短路。
时间复杂度
空间复杂度
代码
#include <bits/stdc++.h> using namespace std; using ll = long long; int n, m; int d[1007], e[1007], se[1007]; bool vis[1 << 10 + 1]; int dis[1 << 10 + 1]; struct node { int v, w; friend bool operator<(const node &a, const node &b) { return a.w > b.w; } }; priority_queue<node> pq; void dijkstra(int st) { for (int i = 0;i < (1 << n);i++) dis[i] = 1e9, vis[i] = 0; dis[st] = 0; pq.push({ st,0 }); while (!pq.empty()) { int u = pq.top().v; pq.pop(); if (vis[u]) continue; vis[u] = 1; for (int i = 1;i <= m;i++) { int v = (u & ~e[i]) | se[i]; int w = d[i]; if (dis[v] > dis[u] + w) { dis[v] = dis[u] + w; pq.push({ v,dis[v] }); } } } } bool solve() { cin >> n >> m; int st = 0; for (int i = 0;i < n;i++) { char ch; cin >> ch; st |= (ch == '1') << i; } for (int i = 1;i <= m;i++) { cin >> d[i]; e[i] = 0, se[i] = 0; for (int j = 0;j < n;j++) { char ch; cin >> ch; e[i] |= (ch == '1') << j; } for (int j = 0;j < n;j++) { char ch; cin >> ch; se[i] |= (ch == '1') << j; } } dijkstra(st); cout << (dis[0] >= 1e9 ? -1 : dis[0]) << '\n'; return true; } int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int t = 1; cin >> t; while (t--) { if (!solve()) cout << -1 << '\n'; } return 0; }
本文来自博客园,作者:空白菌,转载请注明原文链接:https://www.cnblogs.com/BlankYang/p/17539799.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
2022-07-10 POJ1984 Navigation Nightmare
2022-07-10 POJ1417 True Liars
2022-07-10 POJ1456 Supermarket
2022-07-10 NC235745 拆路
2022-07-10 NC51097 Parity game
2022-07-10 NC16884 [NOI2001]食物链
2022-07-10 NC24608 [USACO 2011 Ope S]Learning Languages