Codeforces Round 973 (Div. 2)
C. Password Cracking (C)#
若字符串只向一个方向延伸,则一定能通过 \(2n\) 次询问获得结果;可以先向后猜测,当该侧继续添加字符1与0都不符合要求时、说明已经到达字符串末端,继续询问前缀即可。
void solve() { int n; cin >> n; string s = ""; bool flag = 0; while(s.size() < n) { if(flag) { cout << "? 0" << s << endl; // 似乎endl自带清空缓存区的功能 int ok; cin >> ok; if(ok) s = "0" + s; else s = "1" + s; } else { cout << "? " << s << '0' << endl; int ok; cin >> ok; if(ok) s += "0"; else { cout << "? " << s << '1' << endl; cin >> ok; if(ok) s += "1"; else flag = 1; } } } cout << "! " << s << endl; }
D. Minimize the Difference (D)#
似乎挺典的一道题,虽然vp的时候先写E去了没过
由于每次操作只能对前项减1、后项加1,得到的最终序列一定单调不降。用单调栈维护最终序列中元素的大小与数量,后项出现较小数时依次出栈,即可保证复杂度为 \(O(n)\).(有一说一题解的单调栈写得比我好看多了,呜)
void solve() { int n; scanf("%d", &n); for(int i = 1; i <= n; i++) { scanf("%lld", &a[i]); } int it = 0; for(int i = 1; i <= n; i++) { ll sum = a[i]; int cur = 1; while(it && s[it] >= sum / cur) { sum += s[it] * cnt[it]; cur += cnt[it]; it--; } if(sum % cur) { s[it + 1] = sum / cur, s[it + 2] = sum / cur + 1; cnt[it + 1] = cur - (sum % cur), cnt[it + 2] = sum % cur; it += 2; } else { s[it + 1] = sum / cur, cnt[it + 1] = cur; it++; } } printf("%lld\n", s[it] - s[1]); }
另有:lzz用二分过的,明天去学学他的写法)
E. Prefix GCD (E)#
使用上一场D题的结论可以很快做出这题,每次贪心地将能够最小化gcd的值换到当前位置上,若gcd已经达到最小值,之后元素顺序对答案没有影响。
void solve() { int n; scanf("%d", &n); int g = 0; for(int i = 1; i <= n; i++) { scanf("%d", &a[i]); g = __gcd(g, a[i]); } sort(a + 1, a + n + 1); int cur = 0; for(int i = 1; i <= n; i++) { int mg = INF, mi; for(int j = i; j <= n; j++) { int d = __gcd(cur, a[j]); if(d < mg) mg = d, mi = j; } swap(a[i], a[mi]); cur = mg; if(mg == g) break; } cur = 0; ll ans = 0; for(int i = 1; i <= n; i++) { cur = __gcd(cur, a[i]); ans += cur; } printf("%lld\n", ans); }
(虽然上场D题现在还是TLE状态,但至少结论记住了,也算补完了吧)
F1. Game in Tree (Easy Version) (F1)#
游戏过程可抽象为:Alice和Bob沿 \(1\) 至 \(u\) 的最短路径相向而行,可以选择在任一时刻进入当前节点下与路径不重合的子树,而子树的最大深度是确定的,可以预处理得到。对Alice而言,若当前最大深度与其经过的长度之和已经大于Bob可以选择的路径最大值,进入子树即为必胜态;对Bob同理。若两人一直选择留在路径上,判断相遇时的步数差即可。
// 这题我的代码好难看。。。 vector <int> v[N]; int dep[N], fa[N]; void pre(int f, int i) { fa[i] = f, dep[i] = dep[f] + 1; for(int t : v[i]) { if(t == f) continue; pre(i, t); } } int mx[N], sub[N]; bool on[N]; void dfs(int i) { mx[i] = sub[i] = dep[i]; for(int t : v[i]) { if(t == fa[i]) continue; dfs(t); if(!on[t]) sub[i] = max(sub[i], mx[t]); mx[i] = max(mx[i], mx[t]); } } int len, p[N], sa[N][20], sb[N][20]; int qa(int l, int r) { if(l > r) return 0; int k = __lg(r - l + 1); return max(sa[l][k], sa[r - (1 << k) + 1][k]); } int qb(int l, int r) { if(l > r) return 0; int k = __lg(r - l + 1); return max(sb[l][k], sb[r - (1 << k) + 1][k]); } void solve() { int n; scanf("%d", &n); for(int i = 1; i <= n; i++) { v[i].clear(); } for(int i = 1; i < n; i++) { int x, y; scanf("%d%d", &x, &y); v[x].push_back(y); v[y].push_back(x); } pre(0, 1); int a, b; scanf("%d%d", &a, &b); len = 0; fill(on + 1, on + n + 1, 0); for(int i = a; i; i = fa[i]) { p[++len] = i, on[i] = 1; } dfs(1); for(int i = 1; i <= len; i++) { sa[i][0] = sub[p[i]]; int d = len - i; if(d < i) sa[i][0] = max(sa[i][0], d + (len - d * 2 + 1) / 2); sb[i][0] = i + sub[p[i]] - dep[p[i]]; } for(int k = 1; k <= __lg(len); k++) { for(int i = 1; i + (1 << k) - 1 <= len; i++) { sa[i][k] = max(sa[i][k - 1], sa[i + (1 << k - 1)][k - 1]); sb[i][k] = max(sb[i][k - 1], sb[i + (1 << k - 1)][k - 1]); } } for(int i = 1; i <= len / 2; i++) { int j = len - i + 1; if(sa[j][0] > qb(i, j - 1)) { printf("Alice\n"); return; } if(i == j - 1) break; if(sb[i][0] >= qa(i + 1, j - 1)) { printf("Bob\n"); return; } if(i == j - 2) break; } if(len & 1) printf("Alice\n"); else printf("Bob\n"); }
F2. Game in Tree (Hard Version) (F2)#
没看懂,谁来教教我(哭
作者:Aderose_yr
出处:https://www.cnblogs.com/meowqwq/p/18430919
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
喵喵喵)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现