高斯消元|随机游走 模板

高斯消元

时间复杂度:(O(n^3))

/*
n行:[0,n)
m列:[0,m)
m=2n时,右侧矩阵是左侧矩阵的逆
m=n+1时,右侧一列是左侧方程组的解
*/

//double
double a[][];
bool gauss(int n,int m){
    for(int i=0,r=0;i<n;r=++i){
        for(int j=i+1;j<m;++j)if(abs(a[j][i])>abs(a[r][i]))r=j;
        if(i^r)for(int j=0;j<m;++j)swap(a[i][j],a[r][j]);
        if(abs(a[i][i]-1)<1e-10)return 0;//矩阵非奇异或方程组无解
        double b=a[i][i];
        for(int j=i;j<m;++j)a[i][j]=a[i][j]/b;
        for(int k=0;k<n;++k){
            if(k==i)continue;
            double p=a[k][i];
            for(int j=i;j<m;++j)a[k][j]-=p*a[i][j];
        }
    }
    return 1;
}

//模mod下的解
ll a[][];
bool gauss(int n,int m){
    for(int i=0,r=1;i<n;r=++i){
        for(int j=i+1;j<n;++j)if(a[j][i]>a[r][i])r=j;
        if(i^r)for(int j=0;j<m;++j)swap(a[i][j],a[r][j]);
        if(a[i][i]==0)return 0;//矩阵非奇异或方程组无解
        ll b=qpow(a[i][i],mod-2);
        for(int j=i;j<n;++j)a[i][j]=a[i][j]*b%mod;
        for(int k=0;k<n;++k){//第k行
            if(k==i)continue;
            ll p=a[k][i];
            for(int j=i;j<m;++j)a[k][j]=(a[k][j]-p*a[i][j]%mod+mod)%mod;
        }
    }
    return 1;
}
  • 随机游走

(p(k,x))为经过(k(kge 0))步到达x的概率
令:(P(x)=sum_{k=0}^{+infty}p(k,x)\ e(k,x)=kcdot p(k,x)\ E(x)=sum_{k=1}^{+infty}e(k,x)=sum_{k=1}^{+infty}kcdot p(k,x))

到达终点的期望步数(ans= frac{E(x)}{P(x)})
设:
集合(S(x)={y|y通过某条边可以到达x})
out(x)为点x的出度(终点出度为0,即与终点连接的都是单向边)
有下列两个等式:

  1. (p(k,x)=sum_{yin S(x)}frac{p(k-1,y)}{out(y)},kge 1)且y不能是终点
  2. (frac{e(k,x)}{k}=sum_{yin S(x)}frac{e(k-1,y)}{(k-1)out(y)},kge 2)且y不能是终点

等式1,k从1累加到(+infty)
(p(k,x)=sum_{yin S(x)}frac{p(k-1,y)}{out(y)})

(Rightarrowsum_{k=1}^{+infty}p(k,x)=sum_{yin S(x)}frac{1}{out(y)}left(sum_{k=1}^{+infty}p(k-1,y) ight))

(Rightarrow P(x)-p(0,x)=sum_{yin S(x)}frac{1}{out(y)}P(y))

(Rightarrow P(x)-sum_{yin S(x)}frac{1}{out(y)}P(y)=p(0,x))

等式2,k从2累加到(+infty)

(frac{e(k,x)}{k}=sum_{yin S(x)}frac{e(k-1,y)}{(k-1)out(y)})

(Rightarrowsum_{k=2}^{+infty}frac{e(k,x)}{k}=sum_{yin S(x)}frac{1}{out(y)}sum_{k=2}^{+infty}frac{e(k-1,y)}{k-1})

(Rightarrowsum_{k=2}^{+infty}e(k,x)=sum_{yin S(x)}frac{1}{out(y)}sum_{k=2}^{+infty}left(1+frac{1}{k-1} ight)cdot e(k-1,y))

(Rightarrow E(x)-e(1,x)=sum_{yin S(x)}frac{1}{out(y)}left(E(y)+sum_{k=2}^{+infty}p(k-1,y) ight))

(Rightarrow E(x)-e(1,x)=sum_{yin S(x)}frac{1}{out(y)}left(E(y)+P(y)-p(0,y) ight))

(Rightarrow E(x)-sum_{yin S(x)}frac{E(y)}{out(y)}=sum_{yin S(x)}frac{P(y)-p(0,y)}{out(y)}+p(1,x))

给定一个没有自环的简单图,从0点出发,求到n-1点的期望步数.

double P[],p0[];
//分别是P(x)和p(0,x)
int main(){
    read(n,m);//n个点,m条边
    for(int i=0,x,y;i<m;++i){
        read(x,y);//xy之间有一条边.
        //终点n-1只有入度,没有出度.
        if(x!=n-1){
            mp[x][y]=1,out[x]++;
        }
        if(y!=n-1){
            mp[y][x]=1,out[y]++;
        }
    }
    p0[0]=1;//只有这一个是1,其余全为零
    for(int i=0;i<n;++i){
        for(int j=0;j<n;++j){
            if(mp[j][i]==0)continue;
            a[i][j]=-1.0/(double)s[j];
        }
        a[i][i]=1;
        a[i][n]=p0[i];
    }
    gauss(n,n+1);//求得p(x)
    for(int i=0;i<=n;++i)p[i]=a[i][n];
    for(int i=0;i<n;++i)for(int j=0;j<=n;++j)a[i][j]=0;
    for(int i=0;i<n;++i){
        double tot=0;
        for(int j=0;j<n;++j){
            if(mp[j][i]==0)continue;
            a[i][j]=-1.0/(double)s[j];
            tot+=(p[j]-p0[j])/(double)s[j];
        }
        a[i][i]=1;
        if(mp[0][i])tot+=1.0/(double)s[0];//与起点相邻的点p(1,x)才不为零
        a[i][n]=tot;
    }
    gauss(n,n+1);
    printf("%.5f",a[n-1][n]/p[n-1]);
    return 0;
}

原文地址:https://www.cnblogs.com/foursmonth/p/14155871.html