• 关于有向图走“无限次”后求概率/期望的口胡/【题解】HNCPC2019H 有向图


    关于有向图走“无限次”后求概率/期望的口胡/【题解】HNCPC2019H 有向图

    全是口胡 假了不管

    讨论的都是图(G=(V,E),|V|=n,|E|=m)上的情况

    “走无限次”这个概念很抽象,严谨的证明以及描述和概率的收敛性有关,由于我也不会在此就不讨论这些,但是根据一些概率的知识,可以发现,其实走无限次可以这样描述:

    由于使用概率不好描述在无限次的情况时,每个点和点之间的关系,所以用期望。到时候根据期望的定义式反过来求概率。可能的问题是,“不是走无限次吗,那怎么用期望反过来求概率?”。举个例子,假若只有一个起点且存在那些游戏黑洞(过去了走不来),那么所有随机变量(X=1),所以(E(X)=XP(X)=P(X))

    这是因为期望可以很方便的描述点与点之间的关系(用概率的话,不好描述走无限次的“过程”,在从0次走到无穷次的途中的关系不好用概率描述(因为概率是一个相乘的关系,而期望是相乘且求和(概率不也是吗?我也不知道我在说什么,可能这段话是强行解释,因为我做的题都是用这个得到初始条件的)))

    (e=[f_idots])(i)点的期望构成的行向量,至于我们如何定义“i点的期望”,具体问题具体分析。

    设矩阵(A_{n imes n})是“增广矩阵”(我xjb取的名字),其中(A_{i,j})表示由(i)点转移到(j)点的概率(到底如何定义具体情况具体分析,这里是笼统的口胡),那么走无限次可以这样描述:

    [e imes A=e ]

    然后对比(f_i)系数,
    可以得到(n)个方程。但是这(n)个是解出不来值的(全是 (f_i=0)),为什么?

    这是因为忽略了初始条件,很显然(e imes A=e)有且只有一个解就是(e= 0(A ot = O)) ,必须要根据(f_i)的定义加入初始条件才行(比如(f_i)+=c之类的)。从这里我们可以知道,(f_i)的含义要方便我们加入初始条件。

    由这(n)的个方程可以最坏(O(n^3))解出来所有(f_i)。在(A)矩阵不同的特征或者性质下,可能有别的方法求解(f_i)

    口胡好爽...

    接下来是具体问题具体分析的例子

    【题解】HNCPC2019H 有向图

    有向图

    “照本宣科”,设(f_i)是经过(i)点的期望次数,概率矩阵基本上已经告诉我们了,那么我们直接解就行了。

    然而值得注意的是,由于这个概率矩阵的特性,可以得到(f_i,ile n)的解,然后再求剩下的那些期望。

    方程是

    [f_i= egin{cases} sum_limits{j} A_{j,i}f_j+1 &(n=1) \ sum_limits{j} A_{j,i}f_j &(n>1) end{cases} ]

    高斯消元

    //@winlere
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define DEBUG(s) cerr<<(#s)<<" = "<<(s)<<endl
    
    using namespace std;  typedef long long ll; 
    inline int qr(){
    	register int ret=0,f=0;
    	register char c=getchar();
    	while(!isdigit(c))f|=c==45,c=getchar();
    	while(isdigit(c)) ret=ret*10+c-48,c=getchar();
    	return f?-ret:ret;
    }
    const int mod=1e9+7;
    
    inline int ksm(const int&ba,const int&p){
    	int ret=1;
    	for(int t=p,b=ba;t;t>>=1,b=1ll*b*b%mod)
    		if(t&1) ret=1ll*ret*b%mod;
    	return ret;
    }
    inline int inv(const int&x){return ksm(x,mod-2);}
    
    const int maxn=505;
    int n,m;
    struct MAT{
    	int data[maxn];
    	MAT(){memset(data,0,sizeof data);}
    	inline int&operator[](int x){return data[x];}
    	inline MAT operator *(const int&x){
    		MAT ret;
    		for(int t=1;t<=n+1;++t) ret[t]=1ll*data[t]*x%mod;
    		return ret;
    	}
    	inline MAT operator *=(const int&x){return *this=*this*x;}
    	inline MAT operator -(const MAT&a){
    		MAT ret;
    		for(int t=1;t<=n+1;++t) ret[t]=(data[t]-a.data[t]+mod)%mod;
    		return ret;
    	}
    	inline MAT operator -=(const MAT&a){return *this=*this-a;}
    	inline void print(){
    		for(int t=1;t<=n+1;++t) printf("%d ",data[t]);
    		putchar('
    ');
    	}
    }e[maxn];
    int p[maxn][maxn<<1];
    
    inline void Solve(){
    	for(int t=1;t<=n;++t){
    		e[t]*=inv(e[t][t]);
    		for(int i=1;i<=n;++i)
    			if(i^t) e[i]-=(e[t]*e[i][t]);
    	}
    }
    
    int main(){
    	while(~scanf("%d%d",&n,&m)){
    		memset(e,0,sizeof e);
    		memset(p,0,sizeof p);
    		for(int t=1,in=inv(10000);t<=n;++t)
    			for(int i=1;i<=m+n;++i)
    				p[t][i]=1ll*qr()*in%mod;
    		for(int t=1;t<=n;++t){
    			for(int i=1;i<=n;++i) e[t][i]=p[i][t];
    			e[t][t]=(e[t][t]-1+mod)%mod;
    		}
    		e[1][n+1]=mod-1;
    		Solve();
    		for(int t=1;t<=m;++t){
     			int ans=0;
     			for(int i=1;i<=n;++i) ans=(ans+1ll*e[i][n+1]*p[i][t+n])%mod;
    			printf("%d ",ans);
    		}
    		putchar('
    ');
    	}
    	return 0;
    }
    
    
    
    
  • 相关阅读:
    时间复杂度和空间复杂度的故事
    Go -- 并发编程的两种限速方法
    Go -- type 和断言 interface{}转换
    Go -- 实现二叉搜索树
    Go语言程序的状态监控
    Go -- 中开启gctrace
    Go --- GC优化经验
    Mysql 性能优化20个原则(4)
    Mysql 性能优化20个原则(3)
    查看 activex 组件的方法
  • 原文地址:https://www.cnblogs.com/winlere/p/11852977.html
Copyright © 2020-2023  润新知