• 题解:[BJOI2018]治疗之雨


    题面

    前置芝士: 随机游走模型

    给定一个 (n) 个点 (m) 条边的无向连通图,某位同志想从 (s) 号节点走到 (t) 号节点,每一个节点走向另一个相连的节点有一定概率,求期望步数

    (f_i) 表示为从 (i) 节点到 (t) 节点的期望步数,(p_{i,j}) 表示从节点 (i) 到节点 (j) 的概率

    列出方程组:

    [egin{cases} f_i = displaystyle{sum_{(i,j)in E}^n p_{i,j} imes f_j + 1} & i eq t\ f_t = displaystyle{0}\ \ end{cases} ]

    高斯消元 (mathcal{O}(n^3)) 求解即可

    例题 [HNOI2013]游走


    Solution

    拿到题目,发现每一状态前后都能转移到,无法进行 DP

    可以建立随机游走模型,有 (n+1) 个点,表示当前血量为 0-n ,每个点有一个状态 (E_i)

    对于每一个状态 (E_i) 表示第一个数的数值大小为 (i) 时到达最小值 (0) 的期望步数

    对于每一轮,要么受到减去 (ain [0,k]) ,要么加一,所以只存在向左和向右一个数值的边

    (f_i) 表示 (k) 次伤害,受到 (i) 点伤害的概率

    根据二项式分布有

    (f_i = {k choose i} imes (frac{1}{m+1})^i imes (frac{m}{m+1})^{k-i})

    拆开组合数得

    (f_i = frac{k!}{k!(k-i)!} imes (frac{1}{m+1})^i imes (frac{m}{m+1})^{k-i})

    这个式子是 (mathcal{O}(n)) 的,达标

    先分类讨论

    1. (i) 点血量到 (j(j < i)) 点血量的概率为 (frac{1}{m+1} f_{i-j}+frac{m}{m+1}f_{i-j+1})

    2. (i) 点血量到 (i+1) 点血量的概率为 (frac{1}{m+1}f_0)

    3. (n) 点血量不可有到 (n+1) 的可能性,任意点转来概率都为 (f_{i-j})

    参照模型中的板子,列出方程组

    [egin{cases} E_i = displaystyle{ 1 + frac{1}{m+1} f_0 imes E_{i+1} + sum_{j=1}^i (frac{1}{m+1} f_{i-j}+frac{m}{m+1}f_{i-j+1}) imes E_j} & i eq n\ E_n = displaystyle{ 1 + sum_{j=1}^n f_{n-j} imes E_j}\ \ end{cases} ]

    (nleq 1500) , (mathcal{O}(n^3)) 的高斯消元过不去

    但这里的方程矩阵有一个性质: (1表示有值,0表示无值)

    [quad egin{bmatrix} 1 & 1 & 0 & 0 & 0 & 0 & 0 \ 1 & 1 & 1 & 0 & 0 & 0 & 0 \ 1 & 1 & 1 & 1 & 0 & 0 & 0 \ 1 & 1 & 1 & 1 & 1 & 0 & 0 \ 1 & 1 & 1 & 1 & 1 & 1 & 0 \ 1 & 1 & 1 & 1 & 1 & 1 & 1 \ 1 & 1 & 1 & 1 & 1 & 1 & 1 \ end{bmatrix} quad egin{bmatrix} 1 \ 1 \ 1 \ 1 \ 1 \ 1 \ 1 \ end{bmatrix} ]

    发现消到第 (i) 行时,将第 (i) 列消为 (1) (数值上真正的1) 将这第 (i) 列的以下所有行上的元素消成 (0)

    最终会得到一个形如下图的矩阵

    [quad egin{bmatrix} 1 & 1 & 0 & 0 & 0 & 0 & 0 \ 0 & 1 & 1 & 0 & 0 & 0 & 0 \ 0 & 0 & 1 & 1 & 0 & 0 & 0 \ 0 & 0 & 0 & 1 & 1 & 0 & 0 \ 0 & 0 & 0 & 0 & 1 & 1 & 0 \ 0 & 0 & 0 & 0 & 0 & 1 & 1 \ 0 & 0 & 0 & 0 & 0 & 0 & 1 \ end{bmatrix} quad egin{bmatrix} 1 \ 1 \ 1 \ 1 \ 1 \ 1 \ 1 \ end{bmatrix} ]

    此时 (E_n) 已经求出来了,只要从下往上进行回代即可,时间复杂度 (mathcal{O}(n^2)),达标

    最终答案即为 (E_p)

    Code(C++):

    #include<bits/stdc++.h>
    #define forn(i,s,t) for(int i=(s);i<=(t);++i)
    #define form(i,s,t) for(int i=(s);i>=(t);--i)
    using namespace std;
    typedef long long LL;
    const int N = 1503,Mod = 1e9+7;
    inline LL q_pow(LL p,int k) {            // 快速幂
    	LL Ans = 1;
    	while(k) (k&1 ? Ans=Ans*p%Mod:0),p=p*p%Mod,k>>=1;
    	return Ans;
    }
    int T,n,p;LL m,k,Ans,G[N][N],f[N],fac[N];
    inline void init() {Ans = 0;forn(i,1,min((LL)n+1,k))f[i]=0;forn(i,1,n)forn(j,1,n+1)G[i][j]=0;} // 初始化
    inline int work() {
    	scanf("%d%d%lld%lld",&n,&p,&m,&k);
    	if(!k) return puts("-1"),0;
    	if(!m) if(k == 1) return puts("-1"),0;
    		   else {while(p>0) (p<n?p++:0),p-=k,++Ans;return printf("%lld
    ",Ans),0;} //以上为特殊情况
    	LL inv=q_pow(m+1,Mod-2),invm=q_pow(m,Mod-2);
    	f[0] = q_pow(m*inv%Mod,k);
    	forn(i,1,min((LL)n+1,k)) f[i] = f[i-1]*invm%Mod*q_pow(i,Mod-2)%Mod*(k-i+1)%Mod;  // 线性求f数组
    	forn(i,1,n-1) forn(j,1,i) G[i][j]=(f[i-j]*m+f[i-j+1])%Mod*inv%Mod;
    	forn(i,1,n-1) G[i][i] = (G[i][i]+Mod-1)%Mod,G[i][i+1]=f[0]*inv%Mod;
    	forn(i,1,n) G[i][n+1] = Mod-1;
    	forn(i,1,n) G[n][i] = f[n-i]; G[n][n] = (G[n][n]+Mod-1)%Mod;                     // 以上为列方程
    	forn(i,1,n) {
    		inv = q_pow(G[i][i],Mod-2),G[i][i]=1,G[i][n+1]=G[i][n+1]*inv%Mod;
    		if(i!=n) G[i][i+1] = G[i][i+1]*inv%Mod;
    		forn(j,i+1,n) {
    			G[j][i+1] = (G[j][i+1]-G[j][i]*G[i][i+1]%Mod+Mod)%Mod;
    			G[j][n+1] = (G[j][n+1]-G[j][i]*G[i][n+1]%Mod+Mod)%Mod;
    			G[j][i] = 0;
    		}
    	}                                                                               // 消元具体过程
    	form(i,n,2) G[i-1][n+1]=(G[i-1][n+1]-G[i-1][i]*G[i][n+1]%Mod+Mod)%Mod,
    				G[i-1][i] = 0;                                          // 回代过程
    	printf("%lld
    ",G[p][n+1]);
    	return 0;
    } 
    int main() {
    	scanf("%d",&T);
    	while(T--) init(),work();
    	return 0;
    }
    
  • 相关阅读:
    Windows 7目录
    用wubi安装的Ubuntu在重装Windows 7系统后,如何恢复(转)
    用java查询HBase中某表的一批数据
    hbase数据模型以及编码压缩(转)
    应用Flume+HBase采集和存储日志数据
    HBase性能调优(转)
    【剑指Offer学习】【面试题50:树中两个结点的最低公共祖先】
    [Phonegap+Sencha Touch] 移动开发24 打包wp8.1的App,执行时输入框聚焦弹出软键盘之后,界面上移而不恢复原位的解决的方法
    写在课程设计之后
    String内存溢出异常(错误)可能的原因及解决方式
  • 原文地址:https://www.cnblogs.com/Ax-Dea/p/14033589.html
Copyright © 2020-2023  润新知