The 2024 ICPC Asia East Continent Online Contest (II)
1|0A. Gambling on Choosing Regionals
最差情况就是,强队都和你去一起。因此赛站越小,排名也一定越小。
然后只要动态实现出每个学校最强的若干只队伍就好了。
#include <bits/stdc++.h>
using namespace std;
using i32 = int32_t;
using i64 = long long;
#define int i64
using vi = vector<int>;
using pii = pair<int, int>;
const int inf = INT_MAX / 2;
#define lowbit(x) (x & -x)
struct BinaryIndexedTree {
int n, sum;
vi b;
BinaryIndexedTree(int n) : n(n), b(n + 1) {
sum = 0;
}
void modify(int i, int y) {
sum += y;
for (; i <= n; i += lowbit(i))
b[i] += y;
return;
}
int calc(int i) {
int ans = 0;
for (; i; i -= lowbit(i))
ans += b[i];
return ans;
}
int upper(int x) {
return sum - calc(x);
}
};
i32 main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int n, k;
cin >> n >> k;
int c = inf;
for (int i = 1, x; i <= k; i++)
cin >> x, c = min(c, x);
vector<pair<int, string>> team(n);
vi hw;
for (auto &[w, u]: team)
cin >> w >> u, hw.push_back(w);
sort(hw.begin(), hw.end());
hw.resize(unique(hw.begin(), hw.end()) - hw.begin());
for (auto &[w, u]: team)
w = lower_bound(hw.begin(), hw.end(), w) - hw.begin() + 1;
map<string, vector<pii>> cnt;
for (int i = 0; i < n; i++)
cnt[team[i].second].emplace_back(team[i].first, i);
BinaryIndexedTree bit(hw.size());
for (auto &[u, t]: cnt) {
sort(t.begin(), t.end(), greater<>());
for (int i = 0, N = min(c, (int) t.size()); i < N; i++)
bit.modify(t[i].first, 1);
}
vi res(n);
for (auto &[u, t]: cnt) {
for (int i = 0, N = min(c, (int) t.size()); i < N; i++)
bit.modify(t[i].first, -1);
for (int i = 0; i < t.size(); i++) {
res[t[i].second] = bit.upper(t[i].first) + min(i, c - 1) + 1;
}
for (int i = 0, N = min(c, (int) t.size()); i < N; i++)
bit.modify(t[i].first, 1);
}
for (int i: res) cout << i << "\n";
return 0;
}
2|0E. Escape
你和机器人都不能停留在原地。其次d的限制并不是步数,而是移动半径。
假设你和机器人都可以停留在原地。那么我们可以预处理机器人到达某个点x的最早时间t[x]。
如果你到达x的最早时间为f,则必须要保证f<t[x]。而对于t,可以直接用多源bfs实现。
我们考虑不能停留的情况,机器人不能提前到达你的路上截停你,而是要在你路径上的某个点反复到达离开。如果f<t[x]则无所谓。如果f>t[x],则必须有(f−t[x])mod2=0。然后要知道,机器人不唯一,到达某个点的路径也不唯一。因此我们要分奇偶求出到达每个点的最早时间。同理,在计算你的到达时间时也要分奇偶考虑。
#include <bits/stdc++.h>
using namespace std;
using i32 = int32_t;
using i64 = long long;
#define int i64
using vi = vector<int>;
using pii = pair<int, int>;
const i32 inf = INT_MAX / 2;
const int mod = 998244353;
void solve() {
int n, m, d;
cin >> n >> m >> d;
vector<vi> e(n + 1);
for (int i = 1, x, y; i <= m; i++) {
cin >> x >> y;
e[x].push_back(y), e[y].push_back(x);
}
int k;
cin >> k;
vector t(2, vi(n + 1, inf));
queue<pii> q;
for (int i = 1, x; i <= k; i++) {
cin >> x;
t[0][x] = 0, q.emplace(x, 0);
}
vector vis(2, vi(n + 1));
while (not q.empty()) {
auto [x, tx] = q.front();
q.pop();
if (vis[tx & 1][x]) continue;
vis[tx & 1][x] = 1;
if (tx == d) continue;
for (int ty = tx + 1; auto y: e[x]) {
if (vis[ty & 1][y]) continue;
if (t[ty & 1][y] <= ty) continue;
t[ty & 1][y] = ty, q.emplace(y, ty);
}
}
q.emplace(1, 0);
vis = vector(2, vi(n + 1));
vector f(2, vi(n + 1, inf));
vector lst(2, vi(n + 1, -1));
f[0][1] = 0;
while (not q.empty()) {
auto [x, fx] = q.front();
q.pop();
if (vis[fx & 1][x]) continue;
vis[fx & 1][x] = 1;
for (int fy = fx + 1; auto y: e[x]) {
if (vis[fy & 1][y]) continue;
if (t[fy & 1][y] <= fy) continue;
if (f[fy & 1][y] <= fy) continue;
f[fy & 1][y] = fy, lst[fy & 1][y] = x;
q.emplace(y, fy);
}
}
int ret = min(f[0][n], f[1][n]);
if (ret == inf) {
cout << "-1\n";
return;
}
cout << ret << "\n";
vi p;
for (int x = n, y = ret & 1; x != -1; x = lst[y][x], y ^= 1)
p.push_back(x);
ranges::reverse(p);
for (auto i: p)
cout << i << " ";
cout << "\n";
return;
}
i32 main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int T;
cin >> T;
while (T--)
solve();
return 0;
}
3|0F. Tourist
签到
#include <bits/stdc++.h>
using namespace std;
using i32 = int32_t;
using i64 = long long;
i32 main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int n;
cin >> n;
i64 cnt = 1500;
for (int i = 1, x; i <= n; i++) {
cin >> x, cnt += x;
if (cnt >= 4000) {
cout << i << "\n";
return 0;
}
}
cout << -1;
return 0;
}
4|0G. Game
平局的状态不影响结果。因此我们可以记Alice 获胜的概率是Pa=a0a0+a1,Bob 获胜的概率是Pb=a1a0+a1。
我们可以利用一种类似更相减损术的方法求解。但是复杂度太高了。我们考虑归纳一下。
对于当前的状态(x,y),有以下三种情况
- x=y,此时Alice获胜的概率是Pa
- x<y,此时Alice必须连续至少赢得d=⌈y−xx⌉ 局,才有机会获胜,因此可以递归计算(x,y−dy)
- x>y,此时Bob必须连续至少赢得d=⌈x−yy⌉ 局,才有机会获胜,因此可以递归计算(x−dy,y)
这样的话,复杂度就和辗转相除法一样是O(logn)
#include <bits/stdc++.h>
using namespace std;
using i32 = int32_t;
using i64 = long long;
#define int i64
using vi = vector<int>;
using pii = pair<int, int>;
const i32 inf = INT_MAX / 2;
const int mod = 998244353;
struct mint {
i64 x;
mint(int x = 0) : x(x) {}
int val() const {
return (x % mod + mod) % mod;
}
mint &operator=(int o) { return x = o, *this; }
mint &operator+=(mint o) { return (x += o.x) >= mod && (x -= mod), *this; }
mint &operator-=(mint o) { return (x -= o.x) < 0 && (x += mod), *this; }
mint &operator*=(mint o) { return x = (i64) x * o.x % mod, *this; }
mint &operator^=(int b) {
mint w = *this, ret(1);
for (; b; b >>= 1, w *= w) if (b & 1) ret *= w;
return x = ret.x, *this;
}
mint &operator/=(mint o) { return *this *= (o ^= (mod - 2)); }
friend mint operator+(mint a, mint b) { return a += b; }
friend mint operator-(mint a, mint b) { return a -= b; }
friend mint operator*(mint a, mint b) { return a *= b; }
friend mint operator/(mint a, mint b) { return a /= b; }
friend mint operator^(mint a, int b) { return a ^= b; }
};
void solve() {
int x, y, _;
cin >> x >> y;
mint a, b;
cin >> a.x >> b.x >> _;
mint pa = a / (a + b), pb = b / (a + b);
auto calc = [pa, pb](auto &&calc, int x, int y, mint p) -> mint {
if (x == y) return p * pa;
if (x < y) {
int d = (y - x + x - 1) / x;
return calc(calc, x, y - d * x, p * (pa ^ d));
} else {
int d = (x - y + y - 1) / y;
return p * (1 - (pb ^ d)) + calc(calc, x - d * y, y, p * (pb ^ d));
}
};
cout << calc(calc, x, y, mint(1)).val() << "\n";
}
i32 main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int T;
cin >> T;
while (T--)
solve();
return 0;
}
5|0I. Strange Binary
4的倍数无解,然后我们考虑先构造奇数,然后在加1即可
#include <bits/stdc++.h>
using namespace std;
using i32 = int32_t;
using i64 = long long;
#define int i64
using vi = vector<int>;
using pii = pair<int, int>;
const i32 inf = INT_MAX / 2;
const int mod = 998244353;
void solve() {
int n;
cin >> n;
if (n % 4 == 0) {
cout << "NO\n";
return;
}
bool ok = false;
if (n % 2 == 0) {
ok = true;
n--;
}
vi a(32, -1);
a[31] = 1, n /= 2;
for (int i = 0; i < 31; i++)
if (n >> i & 1) a[i] = 1;
if (ok) a[0] = 0;
cout << "YES";
for (int i = 0; i < 32; i++)
cout << " \n"[i % 8 == 0] << a[i];
cout << "\n";
return;
}
i32 main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int T;
cin >> T;
while (T--)
solve();
return 0;
}
6|0J. Stacking of Goods
可以证明按照ciwi排序一定最优,剩下的贪心就好了。
#include <bits/stdc++.h>
using namespace std;
using i32 = int32_t;
using i64 = long long;
#define int i64
using vi = vector<int>;
using pii = pair<int, int>;
i32 main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int n;
cin >> n;
vi w(n), c(n);
int res = 0;
for (int i = 0, v; i < n; i++) {
cin >> w[i] >> v >> c[i];
res += v;
}
vi p(n);
iota(p.begin(), p.end(), 0);
sort(p.begin(), p.end(), [&](const int &x, const int &y) -> bool {
return -c[y] * w[x] > -c[x] * w[y];
});
vi W(n);
for (int i = n - 2; i >= 0; i--)
W[p[i]] = W[p[i + 1]] + w[p[i + 1]];
for (auto i: p)
res -= c[i] * W[i];
cout << res;
return 0;
}
7|0L. 502 Bad Gateway
其实可以猜到存在一个阈值x,满足小于等于x时,不做额外的操作,大于x时不断的随机。
对于小于等于x的部分,期望次数就是
然后我们考虑大于x的情况,大于的情况总共有T−x种,每一种的概率都是1T。对于随机,随机到小于等于x的概率为xT,这就是一个简单的几何分布,因此期望就是Tx。当我们随机到小于等于x的情况下,还需要操作的期望是1x+2x+3x⋯+xx。因此大于x部分的期望就是
因此总的期望此时就是
这个式子很遗憾不满足单调性。但是通过打表发现,当T取1,2,3…时,x的取值为
#include <bits/stdc++.h>
using namespace std;
using i32 = int32_t;
using i64 = long long;
using i128 = __int128;
#define int i64
using vi = vector<int>;
using pii = pair<int, int>;
const int inf = LLONG_MAX / 2;
using ldb = long double;
const ldb eps = 1e-12;
i128 gcd(i128 a, i128 b) {
return b ? gcd(b, a % b) : a;
}
ostream &operator<<(ostream &os, i128 x){
string s;
while(x > 0)
s += char(x % 10 + '0'), x /= 10;
reverse(s.begin(), s.end());
os << s;
return os;
}
struct Z {
i128 x, y;
Z() {}
void norm(){
i128 d = gcd(x, y);
x /= d, y /= d;
}
bool operator<(const Z &b) const{
return x * b.y < b.x * y;
}
Z &operator=(Z b) {
x = b.x, y = b.y;
return *this;
}
};
i32 main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int T;
cin >> T;
while(T --){
int n;
cin >> n;
auto calc =[&](int x ) -> Z{
Z ans;
ans.x = (i128)x * x *(x + 1) + (i128)(n - x) * ((i128)n * 2 + x * (x + 1));
ans.y = (i128)n * x * 2;
ans.norm();
return ans;
};
int l = 1 , r = n , ret = -1;
while(l <= r){
int mid = (l + r) / 2;
if(mid * (mid + 1) / 2 >= n) ret = mid, r = mid - 1;
else l = mid + 1;
}
auto res = calc(ret);
cout << res.x << " " << res.y << "\n";
}
return 0;
}
__EOF__

本文链接:https://www.cnblogs.com/PHarr/p/18442957.html
关于博主:前OIer,SMUer
版权声明:CC BY-NC 4.0
声援博主:如果这篇文章对您有帮助,不妨给我点个赞
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
2023-10-01 The 2022 ICPC Asia Shenyang Regional Contest
2023-10-01 Codeforces Round 811 (Div. 3)
2022-10-01 女神训练赛 Round01