首页 > 其他分享 >P3412 仓鼠找sugar II 题解

P3412 仓鼠找sugar II 题解

时间:2023-11-18 21:33:04浏览次数:27  
标签:aligned P3412 int 题解 sum son II times deg

P3412 仓鼠找sugar II 题解

大水题一个

题目大意

给定你一个树,设 \(f_{u, v}\) 表示在树上随机游走的情况下从 \(u\) 走到 \(v\) 的期望步数,求 \(\displaystyle \frac{\sum_{i = 1}^n \sum_{j = 1}^n f_{i, j}}{n^2}\)。

题解

不难想到 dp,不过 \(1e5\) 的范围差点让我怀疑我 \(O(n)\) 的 dp。先设一下状态,设 \(f_u\) 表示 \(u\) 子树内的所有点全都走到点 \(u\) 的期望步数。答案就是以每个点为根时根的 \(f\) 值的和。

考虑怎么转移。

似乎不好直接转,于是想想我们转移时什么东西卡住了我们。假设现在 \(u\) 子树内的所有点都走到了 \(u\),那么我们现在想要让这些点再从 \(u\) 结点走向它的父亲结点,这个期望步数不好直接求。

于是我们再设 \(g_u\) 表示从 \(u\) 结点走到它的父亲结点的期望步数。先来考虑它的转移。\(deg_u\) 表示 \(u\) 结点的度,即与它相连的边数,\(son_u\) 表示 \(u\) 结点的儿子构成的集合。

\[\begin{aligned} g_u &= \frac{1}{deg_u} + \sum_{v \in son_u} \frac{1 + g_v + g_u}{deg_u}\\ deg_u \times g_u &= 1 + \sum_{v \in son_u} (1 + g_v + g_u)\\ &= 1 + (deg_u - 1) + (deg_u - 1) \times g_u + \sum_{v \in son_u} g_v\\ &= deg_u + (deg_u - 1) \times g_u + \sum_{v \in son_u} g_v\\ g_u &= deg_u + \sum_{v \in son_u} g_v \end{aligned}\]

\(g\) 的转移就没了,再来考虑 \(f\)。

\[\begin{aligned} f_u &= \sum_{v \in son_u} f_v + size_v \times g_v \end{aligned}\]

这个非常好理解。

于是可以打 \(n^2\) 了。

换一下根,就 \(O(n)\) 了。

设 \(h(x)\) 为以 \(x\) 为根时 \(x\) 的 \(f\) 值,那么有:

\[\begin{aligned} h_u &= f_u + (h_{fa} - f_u - size_u \times g_u) + (n - size_u) \times (g_{fa} - g_u) \end{aligned}\]

最终答案为 \(\displaystyle \frac{\sum_i^n h_i}{n^2}\)。

然后就没了。

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;

const int M = 100005;
const int mod = 998244353;
int n, f[M], g[M], siz[M], out[M], inv, ans, h[M];
int from[M << 1], to[M << 1], head[M], nex[M << 1], tot;

inline void add_edge(int u, int v) {
    from[++ tot] = u;
    to[tot] = v;
    nex[tot] = head[u];
    head[u] = tot;
}

void dfs1(int u, int fa) {
    g[u] = out[u];
    siz[u] = 1;
    for(int i = head[u]; i; i = nex[i]) {
        int v = to[i];
        if(v == fa)
            continue;
        dfs1(v, u);
        siz[u] += siz[v];
        g[u] = (g[u] + g[v]) % mod;
        f[u] = (f[u] + f[v] + siz[v] * g[v] % mod) % mod;
    }
}

void dfs2(int u, int fa) {
    h[u] = (f[u] + (h[fa] - f[u] + mod - siz[u] * g[u] % mod + mod) % mod + (n - siz[u]) * ((g[fa] - g[u] + mod) % mod) % mod) % mod;
    g[u] = g[u] + (g[fa] - g[u]);
    ans = (ans + h[u]) % mod;
    for(int i = head[u]; i; i = nex[i]) {
        int v = to[i];
        if(v == fa)
            continue;
        dfs2(to[i], u);
    }
}

inline int quick_pow(int base, int ci, int pp) {
    int res = 1;
    while(ci) {
        if(ci & 1)
            res = res * base % pp;
        base = base * base % pp;
        ci >>= 1;
    }
    return res;
}

signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    cin >> n;
    inv = quick_pow(n, mod - 2, mod);
    for(int i = 1; i < n; ++ i) {
        int u, v;
        cin >> u >> v;
        add_edge(u, v);
        add_edge(v, u);
        ++ out[u];
        ++ out[v];
    }
    dfs1(1, 0);
    ans = f[1];
    h[1] = f[1];
    for(int i = head[1]; i; i = nex[i]) 
        dfs2(to[i], 1);
    ans = ans * inv % mod * inv % mod;
    cout << ans;
}

标签:aligned,P3412,int,题解,sum,son,II,times,deg
From: https://www.cnblogs.com/Meteor-streaking/p/17841164.html

相关文章

  • P7775 [COCI2009-2010#2] VUK 题解
    链接这道题卡了我$40$多分钟。其实就是跑两遍广搜,第一遍算出每个点距离树的最小距离,第二遍开个优先队列,算出逃回窝的途中最大可能的离它最近的树的距离的最小值。接下来重点讲一下第二遍广搜。首先,我们要知道,如果我们用queue,那么最先到的点不一定是最优的。所以,我们需要......
  • CF391D1题解
    题目链接题意简述给出若干条平面上线段,找出最大的正+形边长多少。思路不难,但是判断两直线相交要考虑全面。数据不大不多,暴力直接过了。代码#include<bits/stdc++.h>usingnamespacestd;typedefstructline{intsx,sy;intex,ey;};intN,M;linexl[120......
  • [ABC326D] ABC Puzzle 题解
    题目链接解法分析这个问题是一个经典的排列谜题,通过回溯算法来穷举所有可能的字符排列,然后验证是否满足行和列约束。这个解决方案可以用于解决类似的谜题,其中需要满足一定的排列条件。通过仔细考虑约束条件,可以加快解决问题的速度,减少不必要的计算。更详细的我写在代码里了。......
  • LIIF笔记
    20231106链接:2012.09161.pdf(arxiv.org)1.为了解决什么问题?现实视觉世界是连续的,但是我们存放在计算机中的图像却是以离散的二维像素阵列存在。如果我们想训练一个卷积神经网路,我们通常需要将图像调整到相同的大小,这样会牺牲保真度。2.现有方法瓶颈现有的隐式神经表征在3D重......
  • P2678 跳石头 题解
    P2678跳石头链接这道题其实很水我们二分最长距离,最后用$check$函数判断合不合法一下是核心代码$check$函数这样写:boolcheck(intx){ intlast=0,tot=0; for(inti=1;i<=n;i++){ if(a[i]-last<x)tot++; elselast=a[i]; } if(len-last<x)tot++; returntot<......
  • CF1552D题解
    CF1552D题解思路首先,$a_i$的正负不重要,如果$a_i=b_j-b_k$,那么就有$-a_i=b_k-b_j$,读入时将$a_i$全部转化为正数。若满足$a_i+a_j+\ldots+a_k$,那么就可以构造出$b$序列,否则不行。从左到右遍历一遍$a$序列,动态规划推出所有可以组成的和,并判断是否满足上式,时间复杂度$O......
  • CF985C 题解
    CF985C题解思路由题意得知,现在有$n\timesk$块木板需要组装成$n$个木桶,每个木桶由$k$块板组成,容量服从短板原理,要求容量差不得超过$I$,求最大容量和。不管采用什么方法,无疑我们首先需要将板长(数组$a$)从小到大排列。利用贪心算法。先找出与$a_0$的长度差不超过$l$的......
  • UVA10652 Board Wrapping 题解
    LinkUVA10652BoardWrappingQuestion给出\(N\)个矩形,求面积最小的凸多边形能包住所有矩形求矩形面积占凸多边形面积的百分比Solution把矩形的四个顶点拿出来,就可以转化成凸包裸题了Code#include<bits/stdc++.h>usingnamespacestd;constdoubleeps=1e-9;constd......
  • NEFU OJ Problem1487 时空乱流题解
    时空乱流Problem:ETimeLimit:1500msMemoryLimit:65535KDescription星际飞行员Alice在一次航行中遭遇了时空乱流,时空乱流将导致Alice乘坐的飞船在n个位面之间穿梭。星际宇航局管理员Bob收到了Alice的求救信号,决定在某些位面上设立监测站,当Alice进入某个已经设立监......
  • 代码随想录算法训练营第七天 | ● 454.四数相加II ● 383. 赎金信 ● 15. 三数之和
    今日学习的文章链接和视频链接https://programmercarl.com/链表理论基础.html●454.四数相加IIvarfourSumCount=function(nums1,nums2,nums3,nums4){letcount=0letmap=newMap();for(letnumber1ofnums1){for(letnumber2ofnums......