• CF618G Combining Slimes


    输出是浮点数,发现合成到 (50) 以上的数字的概率已经很小了,可以忽略。

    (a_{i,j},b_{i,j}) 表示用长度为 (i) 的格子合成数字 (j) 的概率,其中 (b_{i,j}) 表示第一个数字必须为 (2),得 (a_{i,j}=a_{i,j-1} imes a_{i-1,j-1},b_{i,j}=b_{i,j-1} imes a_{i-1,j-1})。不难发现当 (i>j) 时有 (a_{i+1,j}=a_{i,j},b_{i+1,j}=b_{i,j})

    ({a}'_{i,j},{b}'_{i,j}) 表示最终序列倒数第 (i) 个格子合成数字 (j) 的概率,得 ({a}'_{i,j}=a_{i,j}(1-a_{i-1,j}),{b}'_{i,j}=b_{i,j}(1-a_{i-1,j}))

    考虑 (DP),设 (f_{i,j}) 表示当最终序列倒数第 (i) 个格子为 (j) 时,倒数 (i) 个数字和的期望,得:

    [large f_{i,j}= egin{cases} frac{1}{sumlimits_{k=1}^{j-1}{a}'_{i-1,k}}left(sumlimits_{k=1}^{j-1}f_{i-1,k} imes {a}'_{i-1,k} ight)+j &j eq 1 \ frac{1}{sumlimits_{k=2}^{50}{b}'_{i-1,k}}left(sumlimits_{k=2}^{50}f_{i-1,k} imes {b}'_{i-1,k} ight)+j &j=1 end{cases} ]

    预处理前 (50) 项后矩阵快速幂即可。

    #include<bits/stdc++.h>
    #define maxn 60
    using namespace std;
    template<typename T> inline void read(T &x)
    {
        x=0;char c=getchar();bool flag=false;
        while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        if(flag)x=-x;
    }
    int n,lim=50;
    double p,ans,s;
    double a[maxn][maxn],b[maxn][maxn],f[maxn][maxn];
    struct matrix
    {
        double a[maxn][maxn];
    }m,v;
    matrix operator * (const matrix &x,const matrix &y)
    {
        matrix z;
        memset(z.a,0,sizeof(z.a));
        for(int k=0;k<=lim;++k)
            for(int i=0;i<=lim;++i)
                for(int j=0;j<=lim;++j)
                    z.a[i][j]+=x.a[i][k]*y.a[k][j];
        return z;
    }
    int main()
    {
        read(n),scanf("%lf",&p),p/=(double)1000000000;
        for(int i=1;i<=lim;++i) a[i][1]=p,a[i][2]=b[i][2]=1-p;
        for(int i=2;i<=lim;++i)
            for(int j=2;j<=lim;++j)
                a[i][j]+=a[i][j-1]*a[i-1][j-1],b[i][j]+=b[i][j-1]*a[i-1][j-1];
        for(int i=lim;i;--i)
            for(int j=1;j<=lim;++j)
                a[i][j]*=1-a[i-1][j],b[i][j]*=1-a[i-1][j];
        f[1][1]=1,f[1][2]=2;
        for(int i=2;i<=lim;++i)
        {
            for(int j=2;j<=lim;++j)
            {
                s=0;
                for(int k=1;k<j;++k) f[i][j]+=f[i-1][k]*a[i-1][k],s+=a[i-1][k];
                f[i][j]=f[i][j]/s+j;
            }
            s=0;
            for(int k=2;k<=lim;++k) f[i][1]+=f[i-1][k]*b[i-1][k],s+=b[i-1][k];
            f[i][1]=f[i][1]/s+1;
        }
        if(n<=lim)
        {
            for(int i=1;i<=n+1;++i) ans+=f[n][i]*a[n][i];
            printf("%.15lf",ans);
            return 0;        
        }
        v.a[0][0]=m.a[0][0]=1;
        for(int i=1;i<=lim;++i) v.a[0][i]=f[lim][i],m.a[0][i]=i;
        for(int i=2;i<=lim;++i)
        {
            s=0;
            for(int j=1;j<i;++j) m.a[j][i]+=a[lim][j],s+=a[lim][j];
            for(int j=1;j<i;++j) m.a[j][i]/=s;
        }
        s=0;
        for(int j=2;j<=lim;++j) m.a[j][1]+=b[lim][j],s+=b[lim][j];
        for(int j=2;j<=lim;++j) m.a[j][1]/=s;
        n-=lim;
        while(n)
        {
            if(n&1) v=v*m;
            m=m*m,n>>=1;
        }
        for(int i=1;i<=lim;++i) ans+=v.a[0][i]*a[lim][i];
        printf("%.15lf",ans);
        return 0;
    }
    
  • 相关阅读:
    关于git远程被覆盖的问题
    java.lang.UnsupportedClassVersionError:JDK版本不一致报错
    Git学习-上传项目到github
    Servlet+jsp用户登录加上验证码
    Ajax校验--最近更新
    数据校验
    文件上传--多文件上传
    文件上传
    类型转换
    Struts 2 --ONGL介绍
  • 原文地址:https://www.cnblogs.com/lhm-/p/14451388.html
Copyright © 2020-2023  润新知