• bzoj_2676_Contra


    我定义的状态数组存的是概率,而且是正推

    达哥存的是期望,还逆推,然后我就懵比了

    $f_{i,j,k}$ 第i关 j条命 连胜k次

    $$f_{i+1,min(j+1,Q),min(k+1,R)}+=f_{i,j,k}*p$$

    $$f_{i+1,j-1,0}+=f{i,j,k}*(1.0-p)$$

    $$ans=sum_{i=1}^nsum_{j=0}^Qsum_{k=1}^R f_{i,j,k}*j$$

    然后暴力dp会了,考虑矩阵乘优化

    首先两维压成一维

    剪枝:

    1.命数!=Q&&命数<连胜数 就不用压

    然后还可以再加一个位置,用来存期望

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    #include <iostream>
    #include <cmath>
    #define mem(a,b) memset(a,b,sizeof(a))
    #define ll long long
    #define rint register int
    #define dd double
    #define esp 0.0000001
    using namespace std;
    inline void read(int &x)
    {
        x=0; char q=getchar();
        while(q<'0'||q>'9') q=getchar();
        while(q>='0'&&q<='9') x=x*10+q-'0',q=getchar();
    }
    
    int n,R,Q,S;
    dd f[2][7][10006];
    
    dd dp(dd p)
    {
        rint i,j,k; int nx,t1,t2,now=0;
        dd ans=0;
        for(j=0;j<7;++j)
            for(k=0;k<10006;++k)
                f[1][j][k]=0;
        f[1][Q][0]=1;
        for(i=0;i<n;++i)
        {
            now^=1; nx=now^1;
            for(j=0;j<=Q;++j)
                for(k=0;k<=R;++k)
                    f[nx][j][k]=0;
            for(j=1;j<=Q;++j)
                for(k=0;k<=R;++k)
                {
                    t1=j+1; if(t1>Q) t1=Q;
                    t2=k+1; if(t2>R) t2=R;
                    f[nx][t1][t2]+=f[now][j][k]*p;
                    f[nx][j-1][0]+=f[now][j][k]*(1.0-p);
                }
            for(j=0;j<=Q;++j)
                for(k=0;k<=R;++k)
                    ans=ans+f[nx][j][k]*k;
        }
        return ans;
    }
    
    dd work()
    {
        dd l=0,r=1,mid;
        while(l<r-esp)
        {
            mid=(l+r)/2.0;
            if(dp(mid)>=S) r=mid;
            else l=mid;
        }
        return l;
    }
    
    int main(){
        
        //freopen("in.in","r",stdin);
        
        read(n); read(R); read(Q); read(S);
        //printf("%lf",dp(1));
        printf("%lf",work());
    }
    bao_li
    #pragma GCC optimize("O3")
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    #include <iostream>
    #include <cmath>
    #define mem(a,b) memset(a,b,sizeof(a))
    #define ll long long
    #define rint register int
    #define dd double
    #define esp 0.00000001
    using namespace std;
    inline void read(int &x)
    {
        x=0; char q=getchar();
        while(q<'0'||q>'9') q=getchar();
        while(q>='0'&&q<='9') x=x*10+q-'0',q=getchar();
    }
    inline void readll(ll &x)
    {
        x=0; char q=getchar();
        while(q<'0'||q>'9') q=getchar();
        while(q>='0'&&q<='9') x=x*10+q-'0',q=getchar();
    }
    
    int all,dui[10][31];
    struct QTQ
    {
        dd b[155][155];
        void clear()
        {
            mem(b,0);
        }
        void out()
        {
            printf("
    ");
            for(int i=1;i<=all;++i)
            {
                for(int j=1;j<=all;++j)
                    printf("%lf ",b[i][j]);
                printf("
    ");
            }
            printf("
    ");
        }
        QTQ operator * (const QTQ &c) const
        {
            QTQ x=*this,t; rint i,j,k;
            for(i=1;i<=all;++i)
                for(j=1;j<=all;++j)
                {
                    t.b[i][j]=0;
                    for(k=1;k<=all;++k)
                        t.b[i][j]+=x.b[i][k]*c.b[k][j];
                }
            return t;
        }
    }f,a,a1,a2;
    
    int n,R,Q;
    ll S;
    
    dd dp(dd p)
    {
        rint i,j;
        f.clear(); a1.clear(); a2.clear();
        for(i=1;i<=Q;++i)
            for(j=0;j<=R;++j)
                if(i>=j||i==Q)
                {
                    a1.b[dui[i][j]][dui[min(i+1,Q)][min(j+1,R)]]=p;
                    a1.b[dui[i][j]][dui[i-1][0]]=(1.0-p);
                }
        a1.b[all][all]=1;
        for(i=0;i<=Q;++i)
            for(j=0;j<=R;++j)
                if(i>=j||i==Q)
                    a2.b[dui[i][j]][all]=j;
        for(i=1;i<=all;++i) a2.b[i][i]=1;
        a=a1*a2;
        f.b[1][dui[Q][0]]=1;
        int ci=n;
        while(ci)
        {
            if(ci&1)
                f=f*a;
            a=a*a;
            ci>>=1;
        }
        return f.b[1][all];
    }
    
    dd work()
    {
        dd l=0,r=1,mid;
        while(l<r-esp)
        {
            mid=(l+r)/2.0;
            if(dp(mid)>=S) r=mid;
            else l=mid;
        }
        return l;
    }
    
    int main(){
        
        //freopen("in.in","r",stdin);
        //freopen("out.out","w",stdout);
        
        //freopen("nt2012_contra.in","r",stdin);
        //freopen("nt2012_contra.out","w",stdout);
        
        rint i,j;
        
        read(n); read(R); read(Q); readll(S);
        all=0;
        for(i=0;i<=Q;++i)
            for(j=0;j<=R;++j)
                if(i>=j||i==Q)
                    dui[i][j]=++all;
        ++all;
        if(dp(1.0)<=S)// ... 必须是<=,不然第一个点... 
        {
            printf("Impossible.
    ");
            return 0;
        }
        printf("%lf",work());
    }
    ju_zhen_you_hua
  • 相关阅读:
    Linux 常用命令
    去除重叠区间
    Python 小工具之大文件去重
    有趣的pyfiglet
    杨辉三角
    Paginator分页
    Linux用户和用户组
    Grub介绍
    Linux系统运行级别
    Linux系统启动流程
  • 原文地址:https://www.cnblogs.com/A-LEAF/p/7725895.html
Copyright © 2020-2023  润新知