随机游走问题

article/2025/8/23 16:20:40

随机游走指的是在一个点以等可能的概率走向下一个点。

问题1:

Link:https://www.luogu.com.cn/problem/P3232

题意:这道题其实相当于求每条边经过的期望次数。

思路:每条边经过的期望次数不好算,我们想到点经过的期望次数。于是有公式:

f< u,v>=\frac{E(u)}{deg(u)}+ \frac{E(v)}{deg(v)}

这个公式是显而易见的,它的含义是每条边经过的期望次数相当于从这条边的两个端点出发选择这条边的概率。于是我们就成功将这道题转化为求每个点经过的期望概率。而每个点经过的期望概率就是这个点由其直接相邻的点到达的期望。可能有点绕,但写成公式还是比较好理解的。

E(u)=\displaystyle\sum_{e(u,v)\epsilon E}\frac{E(v)}{deg(v)}

需要特别指明的是,1号节点由于是出发点,我们需要+1,以保证初始就经过1号节点这个条件。

初次之外,第n个点期望经过次数应该为0,否则就结束了。这种形式我们就可以写高斯消元了。

高斯消元的板子

void Gauss(int n,double **a,double *b,double *x)
{for(int i=1;i<=n;++i){int p=i;for(int k=i+1;k<=n;++k)if(fabs(a[k][i])>fabs(a[p][i]))p=i;if(i!=p)swap(a[i],a[p]),swap(b[i],b[p]);for(int k=i+1;k<=n;++k){double d=a[k][i]/a[i][i];b[k]-=d*b[i];for(int j=i;j<=n;++j)a[k][j]-=d*a[i][j];} }for(int i=n;i>=1;--i){for(int j=i+1;j<=n;++j)b[i]-=x[j]*a[i][j];x[i]=b[i]/a[i][i];}
} 

ac代码

#include<bits/stdc++.h>
using namespace std; 
typedef long long ll;
const int mod=998244353;//1000000007;
const int inf=0x3f3f3f3f;
const int N=1e5+10;
const int M=5e5+10;
const int tt=(int)(log2(N))+1;
ll qcm(ll a,ll b,ll mod)
{ll res=1ll;while(b){if(b&1ll)res=res*a%mod;a=a*a%mod;b>>=1ll;}return res;
}
int bsgs(int a, int b, int mod)
{map<int, int> mp;int cur = 1, t = (int)sqrt(mod) + 1;for(int B = 0; B < t; ++B){mp[b*cur%mod] = B;cur = (ll)cur * a % mod;}int now = cur;for(int A = 1; A <= t; ++A){if(mp.find(now)!=mp.end()) return (ll)A * t - mp[now];now = (ll)now * cur % mod;}return -1;
}
void Gauss(int n,double a[][510],double *b,double *x)
{for(int i=1;i<=n;++i){int p=i;for(int k=i+1;k<=n;++k)if(fabs(a[k][i])>fabs(a[p][i]))p=i;if(i!=p)swap(a[i],a[p]),swap(b[i],b[p]);for(int k=i+1;k<=n;++k){double d=a[k][i]/a[i][i];b[k]-=d*b[i];for(int j=i;j<=n;++j)a[k][j]-=d*a[i][j];} }for(int i=n;i>=1;--i){for(int j=i+1;j<=n;++j)b[i]-=x[j]*a[i][j];x[i]=b[i]/a[i][i];}
} 
int a[510][510],deg[510];
double dp[510],aa[510][510],p[510];
double dd[125010];
void solve()
{int n,m;scanf("%d%d",&n,&m);for(int i=1;i<=m;++i){int x,y;scanf("%d%d",&x,&y);a[x][y]=a[y][x]=i;deg[y]++;deg[x]++;}p[1]=-1;for(int i=1;i<=n;++i){for(int j=1;j<=n;++j){if(i==j)aa[i][j]=-1;else if(a[i][j])aa[i][j]=(double)1/deg[j];}}Gauss(n-1,aa,p,dp);for(int i=1;i<=n;++i){for(int j=i+1;j<=n;++j){if(!a[i][j])continue;dd[a[i][j]]=dp[i]/deg[i]+dp[j]/deg[j];}}sort(dd+1,dd+m+1);double ans=0;for(int i=1;i<=m;++i)ans+=dd[i]*(m-i+1);printf("%.3lf\n",ans);
}
void init()
{}
int main()
{int T=1;//init();//scanf("%d",&T);while(T--)solve();return 0;
}

问题2:

给定一棵含n个节点的树,q次询问,每次询问两个点的期望步数。

题目链接没找到2333,将就着看吧

思路:对于期望,我们是可以相加的。也就是说如果z在x—>y的必经路上,那么x—>y的期望步数就等于x—>z和z—>y的期望步数之和。既然这样,我们就可以考察每个点走到其父亲节点的期望步数。

dp[x]=\frac{1+\displaystyle\sum_{y\epsilon son(x)} (dp[x]+dp[y]+1)}{deg[x]}

也就是对于每个点,我们可以选择直接往上走,也可以先走到子节点在往上走。

观察这个式子,我们能得出叶子节点的值为1。

再将上式稍作变形,我们得到

dp[x]=deg[x]+\displaystyle\sum_{y\varepsilon son(x)}dp[y]

观察这个式子,我们猜测:

dp[x]=2*size[x]-1

当树的大小(在这里我定义为树的最大深度)是1时,显然成立,我们假设当树的大小不超过k时也成立,则当树的大小为k+1时,将变形后的式子代入得:

dp[x]=deg[x]+\displaystyle\sum_{y\epsilon son(x)}(2*size[y]-1)

整理得;

dp[x]=1+2*\displaystyle\sum_{y\epsilon son(x)}size[y]

又由于,

size[x]=1+\displaystyle\sum_{y\epsilon son(x)}size[y]

于是我们的猜测成立。

写到这里我们算是解决了一小半的问题了,但是还有个问题在困扰着我们,那就x—>y与y—>x的期望步数不一定相等。最简单的反例是其他都相同,但是x节点是作为叶子结点,y节点下面挂着很多子节点,这样两种走法的期望就不一样了,一定要注意这个陷阱。

仿照刚才的思路,我们设G[i]为从父亲节点x走到i的期望步数。同样有方程:

G[i]=\frac{1+G[x]+G[i]+1+\displaystyle\sum_{y\epsilon son(x),y!=i}(1+dp [y]+G[i])}{deg[x]}

化简得,

G[i]=deg[x]+G[x]+\displaystyle\sum_{y\epsilon son(x),y!=i}dp[y]

将dp的值代入得,

G[i]=2*size[x]+G[x]-2*size[i]

到这一步我们的思路似乎就卡住了,算G的值似乎算不了。但是我们考虑换根,将以x为父亲变成以i为父亲,这样我们就能在G[i]和dp[x]之间构架关系。换根之后的dp[x]就等于原先的G[i],于是我们得到

G[i]=2*(n-size[x])-1

到这里,我们就可以使用树上前缀和,或者变成区间求和等等方法计算 ,当然先算dp再取反也是可行的思路。

留坑,等找到题目再写


http://chatgpt.dhexx.cn/article/qcwkdDRF.shtml

相关文章

随机游走 Random Walk

随机游走&#xff08;英语&#xff1a;Random Walk&#xff0c;缩写为 RW&#xff09;&#xff0c;是一种数学统计模型&#xff0c;它是一连串的轨迹所组成&#xff0c;其中每一次都是随机的。[1][2]它能用来表示不规则的变动形式&#xff0c;如同一个人酒后乱步&#xff0c;所…

时间序列:时间序列模型---随机游走过程(The Random Walk Process)

本文是Quantitative Methods and Analysis: Pairs Trading此书的读书笔记。 随机游走过程是一种特殊的ARMA序列。从分子运动到股价波动等现象都被建模为随机游走。 随机游走过程是AR(1)序列&#xff0c;而且,时间序列在时刻的值为&#xff1a; 随机游走过程本质上是到当前时间…

随机游走(Random Walk)算法

随机游走 英文&#xff1a;random walk 定义&#xff1a;随机游走&#xff0c;概念接近于布朗运动&#xff0c;是布朗运动的理想数学状态。 核心概念&#xff1a;任何无规则行走者所带的守恒量都各自对应着一个扩散运输定律。 随机游走算法的基本思想是: 从一个或一系列顶点…

ArrayList分页Lists.partition遇到的坑

一、问题的发现 最近在用分布式任务powerjob的时候&#xff0c;发现了一个关于数组分页之后的序列化问题。事情是这样的&#xff0c;在我执行MapReduce模式的时候&#xff0c;发现了在生成子任务时报了com.esotericsoftware.kryo.kryo5.KryoException: Class cannot be created…

partition list java_Java之Lists.Partition项目中的使用

开心一笑 【媳妇儿问我:“孩子都快出生了,你名字想好了没呀?” 我说:“都想好了,要是生个儿子名字就叫“好帅” 媳妇儿问:“为什么呀?” 我说:“别人看到我就会说,好帅的爸爸。】 提出问题 Java之Lists.Partition在项目中的如何被使用??? 学习地址 解决问题 前言 具…

Lists.partition的使用和里面的坑

作用 partition(List list, int size): 将list集合按指定长度进行切分&#xff0c;返回新的List<List<??>>集合。 案例 引入pom文件 <dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><vers…

Lists.partition集合分组使用以及注意事项

1.介绍 Lists.partition是com.google.common.collect包下的一个方法。 作用是将目标集合按照传入的size分组。 2.使用场景 一般用于固定大小的集合处理&#xff0c;比如&#xff1a;我有两百个商品类型&#xff0c;要求前一百个一种处理方式&#xff0c;后一百个一种处理方…

Guava Lists.transform踩坑小记

1.问题提出 1.前段时间在项目中用到Lists.transform返回的List&#xff0c;在对该list修改后发现修改并没有反映在结果里&#xff0c;研究源码后发现问题还挺大。 下面通过单步调试的结果来查看Guava Lists.transform使用过程中需要注意的地方。 a.对原有的list列表修改会影响L…

Google guava工具类中Lists、Maps、Sets简单使用

Google guava Guava是对Java API的补充&#xff0c;对Java开发中常用功能进行更优雅的实现&#xff0c;使得编码更加轻松&#xff0c;代码容易理解。Guava使用了多种设计模式&#xff0c;同时经过了很多测试&#xff0c;得到了越来越多开发团队的青睐。Java最新版本的API采纳了…

Java常用工具类 : StringUtils、CollectionUtils、ArrayUtils、Lists、Maps等

文章目录 StringUtils引入依赖判断函数 (isNotBlank系列)大小写函数 (转换)删除函数 (remove)字符替换函数 (replace)拆分合并函数 (split)截取函数 (substring)删除空白函数 (trim)判断是否相等函数 (equals)是否包含函数 (contains) CollectionUtils集合判断函数并集、交集、…

Lists的使用

List&#xff08;接口&#xff09;顺序时List最重要的特性&#xff1a;它可保证元素按照规定的顺序排列。List为Collection添加了大量方法&#xff0c;以便我们在List中部插入和删除元素&#xff08;只推荐对LinkedList这样做&#xff09;。List也会生成一个ListIterator&#…

Lists 方法汇总

一、Lists.partition(List<T> list, int size) 将 list 集合按指定长度进行切分&#xff0c;返回新的List<List<T>>集合。 import com.google.common.collect.Lists; import org.junit.Test; import java.util.List;public class ListDemo {Testpublic voi…

LU分解的实现

LU分解是将矩阵分解为一个下三角矩阵和一个上三角矩阵的乘积。矩阵可以不是NxN的矩阵 一个可逆矩阵可以进行LU分解当且仅当它的所有子式都非零。如果要求其中的L矩阵&#xff08;或U矩阵&#xff09;为单位三角矩阵&#xff0c;那么分解是唯一的。同理可知&#xff0c;矩阵的L…

LU分解求线性方程组的解

LU分解是矩阵分解的一种&#xff0c;可以将一个矩阵分解为一个上三角矩阵和一个下三角矩阵的乘积。 LU分解可以用来求逆矩阵&#xff0c;解线性方程组等。本文将介绍LU分解求线性方程组的解。 1.定义 如果A是一个方阵&#xff0c;A的LU分解是将A分解成如下形式: 其中L,U分别为…

矩阵分析——LU分解

LU分解初步 矩阵的LU分解主要用来求解线性方程组或者计算行列式。在使用初等行变换法求解线性方程组的过程中&#xff0c;系数矩阵的变化情况如下&#xff1a; 由上可知&#xff1a; &#xff0c;其中U就是上面矩阵A经过行变换后的上三角矩阵&#xff0c;Eij表示将i行元素与j行…

Doolittle分解法(LU分解)详细分析以及matlab的实现

一、基本介绍 前面介绍的Gauss消去法实际上做的事情是将系数矩阵A做了一个三角分解&#xff0c;即&#xff1a; ALU 式&#xff08;1&#xff09; 其中&#xff0c;L为单位下三角阵&#xff0c;U为上三角阵&#xff0c;该分解唯一。若A为非奇异&#xff0c;则U也非奇异。…

线性代数笔记10——矩阵的LU分解

在线性代数中&#xff0c; LU分解(LU Decomposition)是矩阵分解的一种&#xff0c;可以将一个矩阵分解为一个单位下三角矩阵和一个上三角矩阵的乘积&#xff08;有时是它们和一个置换矩阵的乘积&#xff09;。LU分解主要应用在数值分析中&#xff0c;用来解线性方程、求反矩阵或…

线性代数——LU(LR)分解

文章目录 定义为什么要LU分解为什么能做到LU分解 利用LU分解求行列式值利用LU分解求解线性方程组利用LU分解求逆矩阵对角线上元素有0的情况 定义 定义&#xff1a;给定矩阵A&#xff0c;将A表示成下三角矩阵L和上三角矩阵U的乘积&#xff0c;称为LU分解。再进一步&#xff0c;…

LU分解Matlab算法分析

最近矩阵分析老师出了一道题目作为作业&#xff0c;是一道程序题&#xff0c;题目是对A矩阵做LU分解&#xff0c;要求能对A实现PALU的分解&#xff0c;并最终输出L&#xff0c;U&#xff0c;P矩阵。 先来解读下题目&#xff0c;寥寥几句话&#xff0c;里面囊括的信息量却不少&a…

LU分解,LDLT分解,Cholesky分解

LU分解 如果方阵是非奇异的&#xff0c;即的行列式不为0&#xff0c;LU分解总是存在的。 ALU&#xff0c;将系数矩阵A转变成等价的两个矩阵L和U的乘积&#xff0c;其中L和U分别是下三角和上三角矩阵&#xff0c;而且要求L的对角元素都是1&#xff0c;形式如下&#xff1a; 本…