Luogu P3412 仓鼠找\(sugar\) \(II\)

题目大意:

给定一棵\(n\)个点的树,
仓鼠每次移动都会等概率选择一个与当前点相邻的点,并移动到此点。
现在随机生成一个起点、一个终点(可能相同)。
仓鼠希望知道它从起点走到终点的期望步数是多少。
数据范围:

对于\(30\%\),\(n\leq 5\)
对于\(60\%\),\(n\leq 5\times 10^3\)
对于\(100\%\),\(n \leq 7\times 10^6\)

请将输出答案(一个分数)模上\(998244353\)。

思路与解法

比较套路的一题了......

那个\(30\%\)实在是不会,难道是手玩?

对于 \(60\%\) 的数据:

我们枚举一个树根。设\(f[x]\) 表示 由\(x\) 移动到 \(x\)的父亲\(fa\) 的 期望步数
转移老套路,同这里所介绍的递推式法:
\[f[u] = 1 + \frac{\sum_{v \in son\{u\}}(f[v] + f[u])}{degree(u)}\]
化简一波可得:
\[f[u] = degree(u) + \sum_{v \in son\{u\}} f[v]\]
所以枚举终点,并将终点作为根,然后\(DP\)一遍利用\(size\)统计答案。
时间复杂度\(O(n^2)\),可以跑过\(60\%\)

对于 \(100\%\) 的数据:

其实都会\(60\%\),\(100\%\)简直就是送的......
我们考虑一条边,经过它的路径只有两种情况:从下往上,从上往下。
从下往上的情况我们用上面的\(f[u]\)即可统计。
所以再算一遍从上往下的即可。
设\(g[v]\)表示 从v的父亲\(u\) 移动到 v 的期望步数
用一样的方法设计\(DP\)的转移即可:
\[g[v] = 1 + \frac{(g[u] + g[v]) + \sum_{i \in son\{u\}}^{i \neq v} (f[i] + g[v])}{degree[u]}\]
然后化简一波:
\[g[v] = degree(u) + g[u] + \sum_{i \in son\{u\}}^{i \neq v} f[i] \]
计算答案的公式(考虑路径贡献即可得到):
\[ans = \frac{\sum_{i=1}^n (f[i]+g[i])\times size[i] \times (n - size[i])}{n^2}\]
所以就以 \(1\)号结点为根,只做一遍\(DP\),最后统计答案即可,时间复杂度\(O(n)\)。

实现代码:

注:代码中,\(Work\)函数求\(f[u]\),\(Work2\)函数求\(g[u]\)

#include<bits/stdc++.h>
#define RG register
#define IL inline
#define ll long long
#define _ 100005
#define mod 998244353
using namespace std;

IL int gi(){
    RG int data = 0 , m = 1; RG char ch = 0;
    while(ch != '-' && (ch < '0' || ch > '9'))ch = getchar();
    if(ch == '-'){m = -1; ch = getchar();}
    while(ch >= '0' && ch <= '9'){data = (data << 1) + (data << 3) + (ch ^ 48); ch = getchar(); }
    return ( m ) ? data : -data;
} 

ll f[_],g[_],deg[_],n,m,ans,sz[_];
struct Road{int to , next;}t[2*_]; int head[_],cnt;

IL ll Pow(RG ll T , RG ll js , RG ll S){
    while(js){
        if(js & 1)S = S * T % mod;
        js >>= 1;  T = T * T % mod;
    }return S;
}
IL ll Inv(RG ll x){ return Pow(x , mod - 2 , 1); }

IL void Work(RG int u , RG int fa){
    RG ll b = 0; f[ u ] = 0; sz[u] = 1;
    for(RG int i = head[u] ; i ; i = t[i].next){
        RG int v = t[i].to; if(v == fa)continue;
        Work(v , u); b = b + f[ v ]; if(b >= mod)b -= mod;
        sz[u] += sz[v];
    }
    if(!fa)return;  if(!b){f[ u ] = 1; return;}
    f[ u ] = ( deg[ u ] + b ) ;  if( f[ u ] >= mod )f[ u ] -= mod;
}

IL void Work2(RG int u , RG int fa){
    RG ll b = 0;
    for(RG int i = head[u] ; i ; i = t[i].next){
        RG int v = t[i].to;  if(v == fa)continue;
        b = b + f[ v ];  if(b >= mod)b -= mod;
    }b = (b + g[ u ]) % mod;
    for(RG int i = head[u] ; i ; i = t[i].next){
        RG int v = t[i].to;  if(v == fa)continue;
        g[ v ] = ((deg[u] + b - f[v]) % mod + mod) % mod;
        Work2(v , u);
    }return;
}

int main(){
    freopen("testdata.in","r",stdin);
    n = gi();
    for(RG int i = 1; i <= n - 1; i ++){
        RG int u = gi() , v = gi();
        t[ ++ cnt ] = (Road){ v , head[u] }; head[u] = cnt;
        t[ ++ cnt ] = (Road){ u , head[v] }; head[v] = cnt;
        deg[ u ] ++;  deg[ v ] ++;
    }
    Work(1 , 0); g[1] = g[0] = 0; Work2(1 , 0);
    ans = 0;
    for(RG int i = 1; i <= n; i ++)
        ans = (ans + f[i] * sz[i] % mod * (n - sz[i]) % mod) % mod;
    for(RG int i = 1; i <= n; i ++)
        ans = (ans + g[i] * sz[i] % mod * (n - sz[i]) % mod) % mod;
    ans = ans * Inv(n * n % mod) % mod;
    cout << ans;  return 0;
}

随机推荐

  1. [SCOI2007]最大土地面积

    首先,最大四边形的四个点一定在凸包上 所以先求凸包 有个结论,若是随机数据,凸包包括的点大约是\(\log_2n\)个 然鹅,此题绝对不会这么轻松,若\(O(n^4)\)枚举,只有50分 所以还是要想 ...

  2. composer引用本地git做为源库

    PHP使用者大多对composer是又爱又恨,爱的是composer require后,很多类库不用去下载了,恨的是网速卡成翔,虽然国内有很多道友做了镜象,但对于bower库这些都还是整体更新. 那么 ...

  3. CentOS时间的查看与修改

    [http://www.centoscn.com/CentOS/help/2014/0805/3430.html] 1.查看.修改Linux时区与时间 一.linux时区的查看与修改 1,查看当前时区 ...

  4. Flag

    之前一直怕别人知道你在干什么,其实根本没人在乎你在干什么.做好你自己不就行了,现在这里将成为你的记录生活与学习的地方,尽管目前就你自己,但是你要相信,会有千万人和你在一起,大胆的往前走吧.--- 致自 ...

  5. idea出现Error:Maven Resources Compiler: Maven project configuration required for module 'market' isn't available.

    idea出现如下错误解决办法 1.重新在Build-Rebuild project 既可以解决啦

  6. 编程中&和&&的区别

    逻辑电路中用&: 与门电路,全真为真,有假为假. 编程中:&表示取地址符(C)和 按位与(非bool类型时,转换成二进制,按位与运算). &&表示逻辑与运算,& ...

  7. HDU - 2147 kiki's game 巴什博弈

    思路:以终点(n, m)作为P态,倒推各个坐标的状态,最终得到结论:行数或列数是偶数就能赢,否则输.        AC代码 #include <cstdio> #include < ...

  8. Subsequence Count (线段树)

    Time Limit: 1000 ms   Memory Limit: 256 MB Description 给定一个01串 $S_{1 \cdots n}$ 和 $Q$ 个操作. 操作有两种类型: ...

  9. PhpStorm如何下载github上的代码到本地

    1.看着菜单栏有一个VCS(Virus Capture Scripter)集群服务器的选项,选择其下面的Checkout from Version Control,然后 (1)选择GIT:输入git的 ...

  10. Mybatis的基本使用

    .什么是Mybatis? Mybatis:根据官方解释,MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手工设置参数以及 ...