NOIP 备赛:CF 2E 板刷
从 之前的比赛排着刷。
CF2028 E
这道题主要考察的是手玩能力和转移技巧。
给定一棵树,根为 。爱丽丝的起点位于某个顶点 。她想走出洞口,但不幸的是,红心皇后已经下令处死她。
每分钟都会掷一枚公平的硬币。如果硬币是正面,爱丽丝就可以移动到她当前位置的相邻顶点,反之,红心皇后就可以把爱丽丝拉到皇后选择的相邻顶点。如果爱丽丝最终出现在树的非根叶子上,那么爱丽丝就输了。
假设两人都以最佳方式移动,计算爱丽丝成功逃离每个起始顶点 的概率。对 取模的值。。
首先需要一个 key observation,就是 Alice 的最优策略一定是向父亲走,红心皇后的最优策略一定是向深度最小的叶子走。设每个点深度最小的儿子是 ,Alice 从这个点出发逃离概率是 。那么有转移:
其中 。
这个转移方式有点技巧。假设有链 。那么 。
接下来有 。移项整理得到 。
同样操作可以发现规律 。
首先将树按照浅儿子剖成若干链,对链单独转移,然后再对链顶单独转移即可。预处理逆元可以做到线性。
int f[N], n, m, fa[N], dep[N], s[N];
vector<int> E[N];
void dfs(int u, int F) {
fa[u] = F; for (auto v : E[u]) if (v ^ F) {
dfs(v, u); if (!dep[u]) dep[u] = dep[v] + 1, s[u] = v;
else if (dep[v] + 1 < dep[u]) s[u] = v, dep[u] = dep[v] + 1;
}
}
void dp(int u, int t, int d) {
if (!s[u]) return; dp(s[u], t, d + 1);
f[u] = (d * qpow(d + 1) % mod * f[s[u]] % mod + qpow(d + 1) * t % mod) % mod;
for (auto v : E[u]) if ((v ^ fa[u]) and (v ^ s[u])) dp(v, f[u] % mod, 1);
}
void sub() {
read(n);
rep(i, 1, n) E[i].clear(), dep[i] = 0, s[i] = 0, f[i] = 0;
rop(i, 1, n) {
int a, b; read(a, b);
E[a].push_back(b);
E[b].push_back(a);
} dfs(1, 0); f[1] = 1; dp(1, 1, 0);
rep(i, 1, n) printf("%lld ", f[i]);
return;
}
CF2032 E
这道题考察的主要是观察力和构造水平。
给你一个数组 ,可以进行若干次操作,可以进行任意次操作。
每次操作选择一个位置 ,并且使 ,,。特别地, 的上一个位置是 , 的下一个位置是 ,也就是说,这是一个循环数组。你需要构造一组方案。
首先我们发现这个答案有一定的单调性。即如果能使他们都变成 ,那么也可以通过把他们全操作一遍使他们变成 。因此先设他们能变成一个大数 ,将问题转化为判定性问题。
不妨设 ,则条件充要转化为:,。
发现将每个位置作为开头,剩下的往后顺延,将奇数位置的 的和,减去偶数位置的 的和,得到的就是 。有了这个之后,剩下的就好求了。复杂度是线性的。
void sub() {
read(n);
rep(i, 1, n) read(a[i]);
auto solve = [&](int q) -> bool {
rep(i, 1, n) b[i] = q - a[i];
s[1] = b[1], s[2] = b[2];
rep(i, 3, n) s[i] = s[i - 2] + b[i];
rep(i, 1, n) {
t[i] = s[(i & 1) ? n : n - 1] - s[max(i - 2, 0)];
t[i] += s[i - 1];
t[i] -= s[(i & 1) ? n - 1 : n] - s[max(i - 1, 0)];
t[i] -= s[max(i - 2, 0)];
}
rep(i, 1, n) if (t[i] & 1) return 0; rep(i, 1, n) t[i] >>= 1;
int o = 0; rep(i, 2, n) o += ((i & 1) ? -1 : 1) * t[i]; // p[1] - p[n]
if ((o + t[1]) & 1) return 0;
p[1] = (o + t[1]) >> 1;
rep(i, 2, n) p[i] = t[i] - p[i - 1];
rep(i, 1, n) if (p[i] < 0) return 0;
rep(i, 1, n) printf("%lld ", p[i]); puts("");
return 1;
};
if (solve(I)) return;
if (solve(I + 1)) return;
if (solve(I + 2)) return;
if (solve(I + 3)) return;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示