Luogu P3412 仓鼠找$sugar$ $II$
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;
}
随机推荐
- ionic2+Angular 依赖注入之Subject ——使用Subject来实现组件之间的通信
在Angular+ionic2 开发过程中,我们不难发现,页面之间跳转之后返回时是不会刷新数据的. 场景一:当前页面需要登录之后才能获取数据--去登录,登录成功之后返回--页面需要手动刷新才能获取到数 ...
- [Python Study Notes]字典操作
字典操作 a.增加 >>> info["stu1104"] = "abc" >>> info {'stu1102': 'x5 ...
- shell编程之BASH变量(2)
变量命名规范 在bash中,变量的默认类型都是字符串型,定义 name = 'kk' 变量分类 用户自定义变量.变量自定义的 环境变量:这种变量中主要保存的是和系统操作环境相关的数据.变量可以自定义, ...
- 在Linux/Centos下用wondershaper限速
wondershaper是国外人开发的一款在Linux内核下基于TC工具的对整块网卡的限度工具,虽然有很久没有更新了,但是测试老版本在Centos6.3上依然可以使用. 首先下载wondershape ...
- Three.js 学习笔记(1)--坐标体系和旋转
前言 JavaScript 3D library The aim of the project is to create an easy to use, lightweight, 3D library ...
- POJ 1018 Communication System(贪心)
Description We have received an order from Pizoor Communications Inc. for a special communication sy ...
- [记录]Zabbix3.4配置监控Oracle12c的存活状态和表空间使用率
Zabbix3.4配置监控Oracle的存活状态和表空间使用率 1.安装zabbix3.4 agent: # rpm -ivh http://repo.zabbix.com/zabbix/3.4/rh ...
- Navi.Soft31.任务管理器(定时同步+数据采集)
1系统简介 1.1功能简述 在众多的软件分类中,有几类的软件不是很重要,但也很重要.它们有的是每隔一段时间需要执行一些任务的软件,我们叫它定时类软件:还有一种软件是采集网页中的数据,我们叫它采集类软件 ...
- js闭包面试题目
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Mybatis学习之道(一)
本例子为采用的mysql+maven+mybatis构建. 初步学习mybatis: mybatis为一个半自动框架,相对于hibernate来说他更加轻巧,学习成本更低. 1.新建一个maven工程 ...