首页 > 其他分享 >「CF 123E」Maze

「CF 123E」Maze

时间:2025-01-18 17:34:34浏览次数:1  
标签:p2 int text sum CF times 123E siz Maze

传送门

题意澄清

对于 dfs 遍历时,在某一个点进入子树的顺序并不是按输入顺序,而是假定随机选择未进入过的子树 (这纠结了我好久) 。

破题思路

首先可以明确这题不能推一个 \(O(1)\) 的式子来计算期望 (树的结构是随机的,对于所有点不存在均摊期望的可能) ,但是对于某一刻子树以根节点为起点时,一定是存在一个快速计算期望的式子 (不可能枚举起点还要枚举终点吧) 。

其次,考虑到需要对于每一个点作起点求出期望步数,又是一棵树,故树形 \(dp\) 肯定是必要的,同时还需要换根。

那么算法分析完了(树形 \(dp\) \(+\) 推以子树根作起点的步数期望式子),就要具体实现算法了。

以子树根作起点的期望步数

对于每一棵子树,假设其根为 \(rt\) ,终点在其儿子 \(v\) 的子树中,如果下一步并未走向 \(v\) ,而是走向 \(u\) ,则需要花 \(2\times siz[u]\) ( \(siz[u]\) 为 \(u\) 子树内节点个数1) 步走回 \(rt\) ,那么对于在 \(v\) 之前走向 \(u\) 的概率相当于对于 \(rt\) 所有儿子的排列中 \(v\) 在 \(u\) 之后的概率,明显是 \(\frac{1}{2}\) ,故 \(u\) 子树对于步数的贡献即为 \(2\times siz[u]\times\frac{1}{2}=siz[u]\) ,所以对于以 \(rt\) 为根且以 \(rt\) 为起点的子树,其期望步数为

\[g_{rt} \gets \sum\limits_{u\in son_{rt}} ((siz_{rt}-siz_u)\times sum\_p_u+g_u) \]

其中 \(g_u\) 为在 \(u\) 的子树中以 \(u\) 为根且以 \(u\) 为起点的期望步数,\(sum\_p_u\) 为以 \(u\) 的子树中的结点为终点的概率。

树形dp

对于第一次树形 \(dp\) 的式子我们已经在上一个部分推出来了,难点在于换根时的式子。我经常使用的方法是不去思考意义,只思考原式的 “逆式” 。

先明确一下定义。

\[\begin{aligned} & \text{依据}\ u\ \text{去更新儿子}\ v\\ & g,siz,sum\_p \text{意义同上}\\ & f_u:\text{以}\ u\ \text{为起点的期望步数}\\ & p2_u:\text{以}\ u\ \text{为终点的概率}\\ & except\_v:\text{对于}\ v\ \text{的父亲}\ u\ \text{没有子树}\ v\ \text{时}\ g_u\ \text{的值} \end{aligned} \]

首先我们先处理式子中的 \(g_u\) ,即 \(except\_v\) ,既然是消去影响,故是用 \(f_u\) 去减去影响。

  • 终点不在 \(v\) 的子树中
    概率为 \(1-sum\_p_v-p2_u\)
    贡献为 \(siz_v\)
    影响为 \((1-sum\_p_v-p2_u)\times(siz_v)\)
  • 终点在 \(v\) 的子树中
    概率为 \(sum\_p_v\)
    贡献为 \(n-siz_v\)
    影响为 \(sum\_p_v\times(n-siz_v)\)

\[except\_v \gets f_u - siz_v \times (1 - p2_u - sum\_p_v) - (n - siz_v) \times sum\_p_v \]

接下来我们处理以 \(v\) 为起点的期望步数。

  • 终点在原本 \(v\) 的子树中
    概率为 \(sum\_p_v-p2_v\)
    贡献为 \(n-siz_v\)
    期望步数为 \((sum\_p_v-p2_v)\times(b-siz_v)\)
  • 终点不在原本 \(v\) 的子树中
    模仿原 \(dp\) 式子可得 \((n-(n-siz_v))\times(1-sum\_p_v)+except\_v\)

\[f_v \gets (n - siz_v) \times (sum\_p_v - p2_v) + (n - (n - siz_v)) \times (1 - sum\_p_v) + except\_v \]

实现

综合上述内容,便有了以下代码。

/*
address:https://codeforces.com/problemset/problem/123/E
AC 2024/8/28 12:26
*/
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
vector<int>G[N];
int n;
double p1[N], p2[N];
int sum1, sum2;
double f[N], g[N], sum_p[N];
int siz[N];
inline void dfs1(int u, int fa) {
    sum_p[u] = p2[u];
    siz[u] = 1;
    for (auto v : G[u]) {
        if (v == fa) continue;
        dfs1(v, u);
        sum_p[u] += sum_p[v];
        siz[u] += siz[v];
    }
    for (auto v : G[u]) {
        if (v == fa) continue;
        g[u] += (siz[u] - siz[v]) * sum_p[v] + g[v];
    }
}
inline void dfs2(int u, int fa) {
    for (auto v : G[u]) {
        if (v == fa) continue;
        double except_v = f[u] - siz[v] * (1 - p2[u] - sum_p[v]) - (n - siz[v]) * sum_p[v];
        f[v] = (n - siz[v]) * (sum_p[v] - p2[v]) + (n - (n - siz[v])) * (1 - sum_p[v]) + except_v;
        dfs2(v, u);
    }
}
int main() {
    scanf("%d", &n);
    for (int i = 1;i < n;i++) {
        int u, v;scanf("%d%d", &u, &v);
        G[u].push_back(v);G[v].push_back(u);
    }
    for (int i = 1;i <= n;i++) scanf("%lf%lf", &p1[i], &p2[i]), sum1 += p1[i], sum2 += p2[i];
    for (int i = 1;i <= n;i++) p1[i] /= sum1, p2[i] /= sum2;
    dfs1(1, 0);
    f[1] = g[1];
    dfs2(1, 0);
    double ans = 0;
    for (int i = 1;i <= n;i++) ans += p1[i] * f[i];
    printf("%.12lf", ans);
    return 0;
}

The end

一道概率期望加树形 \(dp\) 的好题,具备一定思维难度,但又可以一步步推出式子,对于学未至极但又学习良多的我是不多的提升较大的练习。

标签:p2,int,text,sum,CF,times,123E,siz,Maze
From: https://www.cnblogs.com/keysky/p/18678632

相关文章

  • CF516E Drazil and His Happy Friends 做题记录
    CF516EDrazilandHisHappyFriendsDescription有\(n\)个男生\(m\)个女生,编号分别为\(0\simn-1\)和\(0\simm-1\)。有\(B\)个男生和\(G\)个女生是快乐的,其他人是不快乐的。在第\(i\)天,编号为\(i\bmodn\)的男生和编号为\(i\bmodm\)的女生会一起......
  • 题解:CF140A New Year Table
    CF140ANewYearTable思路注意到题目中提到了大圆与小圆相切,我们可以计算由两条经过小圆周长与大圆圆心的切线组成的圆心角的度数。但是这个角度其实不好算,所以我们可以求出它一半的正弦值,也就是\(b\div(a-b)\),然后用asin函数求出其度数(以弧度为单位)。最后答案就是判断\(......
  • [CF2048F] Kevin and Math Class 题解
    注意到这里有个区间的\(b_i\)最小。我们考虑每个\(b_i\)作为最小的时候各操作几次。显然每个\(b_i\)的【操作区间】更长是不劣的。于是这些个\(b_i\)是可以打成笛卡尔树,进行DP。想到这一点,DP便是不难的了。定义\(f_{i,j}\)为以\(i\)为根的子树内,最优操作后最大值......
  • AI绘画模型王者归来,majicFlus 模型重磅发布!
    要说SD社区中最受欢迎的大模型,那就必然是麦橘系列了——SD1.5时代的神,majicMIXrealistic麦橘写实模型更是一口气霸占了lib社区最热、最多运行、最多下载三榜第一、最多返图(第二),光lib一个平台就将近1500w的在线运行量,26w的下载量,以往大家说的一脸AI很大程度上......
  • 906 [CF 1117D] Magic Gems
    //906[CF1117D]MagicGems.cpp:此文件包含"main"函数。程序执行将在此处开始并结束。///*http://oj.daimayuan.top/course/22/problem/1046Reziba拥有无限多个魔法宝石,每个魔法宝石的大小为1单元。每个魔法宝石可以被分解为m个普通宝石,每个普通宝石的大小也是1......
  • (14-3-02)基于Latent Diffusion Transformer的文生视频系统:数据集处理(2)加载并处理Taic
    6.4.3 加载并处理Taichi数据集文件taichi_datasets.py实现了一个Taichi数据集类,用于加载和处理分帧存储的视频数据,特别是太极表演相关的帧序列。它包括从数据目录中读取视频帧、按时间进行帧采样、将帧数据转换为张量并应用数据增强等功能。代码通过torch.utils.data.Da......
  • c++基础算法讲解(写了ccf考试中可能出现的各种算法)
    枚举法枚举法是一种基本的问题解决策略,它尝试所有可能的情况以找到解决方案。这种方法通常用于问题规模较小且可以接受一定时间复杂度的情况。例子:找出三个数中最大的数#include<iostream>usingnamespacestd;intfindMax(inta,intb,intc){returnmax(a,......
  • [CF2057G] Secret Message 题解
    神秘题目。题目的条件十分神奇,\(|A|\le\frac{1}{5}(s+p)\),不知所云。一开始尝试用皮克定理转化,但是failed。阅读理解之后发现有一个(很典)的套路,就是构造出五组方案,使得\(\sum_{cyc}|A|=s+p\),这样就一定有一组方案,面积小于等于$\frac{1}{5}(s+p)$。如何构造?我们发现......
  • CF div2 990(A~E)
    VP赛时\(4\)题,发挥得比较不错的一场,并且这场也偏简单。A数数题,找好规律直接模拟即可codeB简单排列组合题显然总方案数为:\[n!/(a_1!*a_2!*...*a_m!)\]\(a_1到a_m\)表示某种字符的数量想最小化总方案数,只能最大化上式分母的值。而题目操作等价于将某个\(a_i\)减......
  • CF1956F Nene and the Passing Game 解题报告
    假设\(j>i\),则:\(i+l_i\lej-l_j,i+r_i\lej-r_j\)所以相当于看区间\([i+l_i,i+r_i]\)和区间\([j-r_j,j-l_j]\)是否有交集可以将这些区间放在数轴上,考虑建虚点,将数轴上的每个点向包含它的区间连边但是这样会有一个问题,记加为右区间,减为左区间,此时就无法判断是哪种区间在相......