【Luogu】 P5643 [PKUWC2018] 随机游走

2023-10-04 17:46

本文主要是介绍【Luogu】 P5643 [PKUWC2018] 随机游走,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目链接

点击打开链接

题目解法

首先考虑 m i n − m a x min-max minmax 容斥
可得 E ( S ) = ∑ T ⊆ S ( − 1 ) ∣ T ∣ − 1 f ( T ) E(S)=\sum\limits_{T\subseteq S}(-1)^{|T|-1}f(T) E(S)=TS(1)T1f(T)
其中 f ( T ) f(T) f(T) 为从 x x x 第一次到达 T T T 集合中任意一点的期望步数
树上随机游走可以想到树上高斯消元,所以开始推式子
g ( i , S ) g(i,S) g(i,S) 为从 i i i 第一次到达 S S S 集合中任意一点的期望步数(后面省略 S S S
g ( i ) = 1 + 1 d e g i f f a + 1 d e g i × ∑ v ∈ s o n ( i ) f v = 1 + 1 d e g i f f a + 1 d e g i × ∑ v ∈ s o n ( i ) ( A v f i + B v ) = 1 + 1 d e g i f f a + ( 1 d e g i × ∑ v ∈ s o n ( i ) A v ) f i + 1 d e g i × ∑ v ∈ s o n ( i ) B v g(i)=1+\frac{1}{deg_i}f_{fa}+\frac{1}{deg_i}\times\sum\limits_{v\in son(i)}f_v\\ =1+\frac{1}{deg_i}f_{fa}+\frac{1}{deg_i}\times\sum\limits_{v\in son(i)}(A_vf_i+B_v)\\ =1+\frac{1}{deg_i}f_{fa}+(\frac{1}{deg_i}\times\sum\limits_{v\in son(i)}A_v)f_i+\frac{1}{deg_i}\times\sum\limits_{v\in son(i)}B_v g(i)=1+degi1ffa+degi1×vson(i)fv=1+degi1ffa+degi1×vson(i)(Avfi+Bv)=1+degi1ffa+(degi1×vson(i)Av)fi+degi1×vson(i)Bv
所以 ( 1 − 1 d e g i × ∑ v ∈ s o n ( i ) A v ) f i = 1 d e g i f f a + 1 + 1 d e g i × ∑ v ∈ s o n ( i ) B v (1-\frac{1}{deg_i}\times\sum\limits_{v\in son(i)}A_v)f_i=\frac{1}{deg_i}f_{fa}+1+\frac{1}{deg_i}\times\sum\limits_{v\in son(i)}B_v (1degi1×vson(i)Av)fi=degi1ffa+1+degi1×vson(i)Bv
f i f_i fi 的系数除过去即可得到 A i , B i A_i,B_i Ai,Bi,式子过于复杂,写了可能也看不清
我们可以钦定 x x x 为根,那么 f ( S ) = B x f(S)=B_x f(S)=Bx
计算 f f f 的时间复杂度为 O ( n 2 n ) O(n2^n) O(n2n)

然后我们发现 m i n − m a x min-max minmax 容斥的式子是一个子集卷积,直接 f w t fwt fwt 即可,时间复杂度 O ( n 2 n ) O(n2^n) O(n2n)
其实不用 f w t fwt fwt 也可以过题,时间复杂度为 O ( q 2 n ) O(q2^n) O(q2n),但常数很小

#include <bits/stdc++.h>
using namespace std;
const int N=20,P=998244353;
int n,q,rt,f[1<<18],cnt[1<<18],A[N],B[N];
int e[N<<1],ne[N<<1],h[N],idx;
inline int read(){int FF=0,RR=1;char ch=getchar();for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;return FF*RR;
}
inline void inc(int &x,int y){x+=y;if(x>=P) x-=P;
}
int qmi(int a,int b){int res=1;for(;b;b>>=1){if(b&1) res=1ll*res*a%P;a=1ll*a*a%P;}return res;
}
void dfs(int u,int fa,int S){if(S>>u&1) return;int rs1=0,rs2=0,deg=(fa>=0);for(int i=h[u];~i;i=ne[i]){int v=e[i];if(v==fa) continue;dfs(v,u,S);deg++;inc(rs1,A[v]),inc(rs2,B[v]);}int ivdeg=qmi(deg,P-2);rs1=(P+1-1ll*rs1*ivdeg%P)%P,rs1=qmi(rs1,P-2);rs2=1ll*rs2*ivdeg%P+1;A[u]=1ll*ivdeg*rs1%P,B[u]=1ll*rs2*rs1%P;
}
void add(int x,int y){ e[idx]=y,ne[idx]=h[x],h[x]=idx++;}
void fwt(){n=1<<n;for(int mid=1;mid<n;mid<<=1)for(int i=0;i<n;i+=mid<<1)for(int j=0;j<mid;j++){f[i+j+mid]+=f[i+j];if(f[i+j+mid]>=P) f[i+j+mid]-=P;}
}
int main(){n=read(),q=read(),rt=read();rt--;memset(h,-1,sizeof(h));for(int i=1;i<n;i++){int x=read(),y=read();x--,y--;add(x,y),add(y,x);}for(int S=0;S<1<<n;S++){for(int i=0;i<n;i++) A[i]=0,B[i]=0;dfs(rt,-1,S),f[S]=B[rt];cnt[S]=__builtin_popcount(S)+1;if(cnt[S]&1) f[S]=P-f[S];}fwt();while(q--){int k=read(),State=0;while(k--){ int x=read();State|=1<<(x-1);}printf("%d\n",f[State]);}fprintf(stderr,"%d ms\n",int(1e3*clock()/CLOCKS_PER_SEC));return 0;
}
/*
f[i][S]:从i出发,第一个到点集S中的点的期望步数
*/

这篇关于【Luogu】 P5643 [PKUWC2018] 随机游走的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/2447

相关文章

Python中的随机森林算法与实战

《Python中的随机森林算法与实战》本文详细介绍了随机森林算法,包括其原理、实现步骤、分类和回归案例,并讨论了其优点和缺点,通过面向对象编程实现了一个简单的随机森林模型,并应用于鸢尾花分类和波士顿房... 目录1、随机森林算法概述2、随机森林的原理3、实现步骤4、分类案例:使用随机森林预测鸢尾花品种4.1

使用C#如何创建人名或其他物体随机分组

《使用C#如何创建人名或其他物体随机分组》文章描述了一个随机分配人员到多个团队的代码示例,包括将人员列表随机化并根据组数分配到不同组,最后按组号排序显示结果... 目录C#创建人名或其他物体随机分组此示例使用以下代码将人员分配到组代码首先将lstPeople ListBox总结C#创建人名或其他物体随机分组

AI学习指南深度学习篇-带动量的随机梯度下降法的基本原理

AI学习指南深度学习篇——带动量的随机梯度下降法的基本原理 引言 在深度学习中,优化算法被广泛应用于训练神经网络模型。随机梯度下降法(SGD)是最常用的优化算法之一,但单独使用SGD在收敛速度和稳定性方面存在一些问题。为了应对这些挑战,动量法应运而生。本文将详细介绍动量法的原理,包括动量的概念、指数加权移动平均、参数更新等内容,最后通过实际示例展示动量如何帮助SGD在参数更新过程中平稳地前进。

AI学习指南深度学习篇-带动量的随机梯度下降法简介

AI学习指南深度学习篇 - 带动量的随机梯度下降法简介 引言 在深度学习的广阔领域中,优化算法扮演着至关重要的角色。它们不仅决定了模型训练的效率,还直接影响到模型的最终表现之一。随着神经网络模型的不断深化和复杂化,传统的优化算法在许多领域逐渐暴露出其不足之处。带动量的随机梯度下降法(Momentum SGD)应运而生,并被广泛应用于各类深度学习模型中。 在本篇文章中,我们将深入探讨带动量的随

HDD 顺序和随机文件拷贝和存储优化策略

对于机械硬盘(HDD),顺序拷贝和随机拷贝涉及到磁头的移动方式和数据的读取/写入模式。理解这些概念对于优化硬盘性能和管理文件操作非常重要。 1. 顺序拷贝 定义: 顺序拷贝指的是数据从硬盘的一个位置到另一个位置按顺序连续读取和写入。这意味着数据在硬盘上的位置是线性的,没有跳跃或回溯。 特点: 磁头移动最小化:由于数据是连续的,磁头在读取或写入数据时只需要在磁盘的一个方向上移动,减少了寻道时

FHQ Treap模版(luogu P3369)

FHQ Treap模版(自用),带注释 #include<bits/stdc++.h>using namespace std;const int N=1e5+10;int n,root,idx;struct node{int l,r;int val,key,size;}tr[N];int getnew(int v){tr[++idx].val=v;//权值tr[idx].key=rand(

算法:将数组随机打乱顺序,生成一个新的数组

一、思路 核心:缩小原数组的可随机取数范围 1、创建一个与原数组长度相同的新数组; 2、从原数组的有效的可取数范围 (不断缩小) 中随机取出一个数据,添加进新的数组; 3、将取出的随机数与原数组的最后一个数据进行置换; 4、重复步骤2和3。 二、代码 public class ArrayRandomTest {//将数组随机打乱顺序,生成一个新的数组public static int

Midjourney 随机风格 (Style Random),开启奇幻视觉之旅

作者:老余捞鱼 原创不易,转载请标明出处及原作者。 写在前面的话:       Midjourney 最近推出了 "Style Random"(随机风格),这项功能可以让我们使用独特的随机 sref 代码创建图像,从而每次都能获得不同的美感。通过对这些功能的探索和尝试,我发现了一些很棒的风格,我很高兴能与大家分享,这样可以节省大家的时间,不用自己动手测试。在本文中,我将展示十个M