zoukankan      html  css  js  c++  java
  • [LnOI2019]加特林轮盘赌

    VI.[LnOI2019]加特林轮盘赌

    我们考虑设\(f[i][j]\)表示\(i\)个人中,第\(j\)个人最终存活的概率。

    我们先考虑\(j>1\)的情况。此时,有\(p\)的概率排在首位的人挂掉,局面变为\(f[i-1][j-1]\);反之,有\(1-p\)的概率首位存活,这就相当于所有人向前进一格,局面变为\(f[i][j-1]\)

    于是我们有

    \[f[i][j]=p\times f[i-1][j-1]+(1-p)\times f[i][j-1]\qquad(1<j\leq i) \]

    下面我们考虑特殊情况\(f[i][1]\)。显然,只有这一枪他幸存下来了,他最终才有可能存活。故我们有

    \[f[i][1]=(1-p)f[i][i] \]

    到这里我们就可以DP了。我们初始有\(f[1][1]=1\);接着,我们从小往大枚举\(i\),更新DP状态。

    我们设\(f[i][1]=a\times f[i][i]+b\)。显然,此时有\(a=1-p,b=0\)。这样,我们就可以把\(f[i][2]\)表示成\(c\times f[i][i]+d\)的形式,接着把\(f[i][3]\)表示成\(e\times f[i][i]+f\)的形式……

    最终,我们得到一个方程:

    \[f[i][i]=x\times f[i][i]+y \]

    直接解该方程即可得出\(f[i][i]\)。再DP一圈即可得出所有的\(f[i][j]\)

    时间复杂度\(O(n^2)\)。(注意特判\(p=0\)时的情况)

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    const long double eps=1e-9;
    int n,m;
    long double p,f[2][10100];
    int main(){
    	cin>>p>>n>>m;
    	if(p<eps){if(m==1)puts("1");else puts("0");return 0;}
    	f[1][1]=1;
    	for(int i=2;i<=n;i++){
    		double a=1,b=0;
    		for(int j=1;j<=i;j++)a*=1-p,b=(1-p)*b+p*f[!(i&1)][j-1];
    		f[i&1][i]=b/(1-a);
    		f[i&1][1]=(1-p)*f[i&1][i];
    		for(int j=2;j<i;j++)f[i&1][j]=(1-p)*f[i&1][j-1]+p*f[!(i&1)][j-1];
    	}
    	printf("%.10Lf\n",f[n&1][m]);
    	return 0;
    } 
    

  • 相关阅读:
    eclipse历史版本下载地址
    注解@SuppressWarnings
    VB创建文件夹
    VB学习生成JavaBean
    C++下的强制转换类型
    Django扩展
    数据查询操作
    深入剖析C++多态、VPTR指针、虚函数表
    快速排序一步一步优化
    cookie与session
  • 原文地址:https://www.cnblogs.com/Troverld/p/14610869.html
Copyright © 2011-2022 走看看