[2018雅礼省选集训3-31]Max 期望DP

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/DOFYPXY/article/details/79952361

注意到m比较小,不妨状压m
我们设fi,j,S表示Ai用掉集合S中的操作后值为j的概率。
再设gi,j,S表示A1..i用掉集合S中的操作后最大值为j的概率,枚举Ai使用的操作集合转移即可。
复杂度O(nc2m23m)
代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define up(x,y) (x=(x+(y))%mod)
#define in(x,s) ((s>>(x-1))&1)
#define ll long long
using namespace std;
const int mod=1000000007;
int n,m,c,pc[1030];
ll P[41][11][4],f[41][31][1030],g[41][31][1030],ans;
int main()
{
    scanf("%d%d%d",&n,&m,&c);
    for(int i=1;i<=m;i++)
        for(int j=1;j<=n;j++)
            for(int k=0;k<=c;k++)
                scanf("%lld",&P[j][i][k]);
    for(int s=0;s<(1<<m);s++)
        for(int t=s;t;t>>=1) pc[s]+=(t&1);
    for(int i=1;i<=n;i++)
    {
        f[i][0][0]=1;
        for(int j=1;j<=m;j++)
            for(int s=0;s<(1<<(j-1));s++)
                for(int k=0;k<=c*(j-1);k++)
                    if(f[i][k][s])
                    for(int l=0;l<=c;l++)
                        up(f[i][k+l][s|(1<<(j-1))],f[i][k][s]*P[i][j][l]);
    }
    g[0][0][0]=1;
    for(int i=1;i<=n;i++)
        for(int s=0;s<(1<<m);s++)
            for(int j=0;j<=pc[s]*c;j++)
                if(g[i-1][j][s])
                    for(int u=((1<<m)-1)^s,t=u;;t=(t-1)&u)
                    {
                        for(int k=0;k<=pc[u]*c;k++)
                            up(g[i][max(j,k)][s+t],g[i-1][j][s]*f[i][k][t]);
                        if(!t) break;
                    }
    for(int i=0;i<=c*m;i++)
        up(ans,g[n][i][(1<<m)-1]*i%mod);                    
    printf("%lld",ans);

    return 0;
}
阅读更多

没有更多推荐了,返回首页