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

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

#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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值